blob: 6d44bb561de45ff6af1a66eafe9c5fd587eeb47e [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;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070027import com.android.server.am.ActivityStack.ActivityState;
Dianne Hackborna924dc0d2011-02-17 14:22:17 -080028import com.android.server.wm.WindowManagerService;
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;
Christian Mehlmauer7664e202010-07-20 08:46:17 +020058import android.content.DialogInterface;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080059import android.content.Intent;
60import android.content.IntentFilter;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070061import android.content.IIntentReceiver;
62import android.content.IIntentSender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -070063import android.content.IntentSender;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080064import android.content.pm.ActivityInfo;
65import android.content.pm.ApplicationInfo;
66import android.content.pm.ConfigurationInfo;
67import android.content.pm.IPackageDataObserver;
68import android.content.pm.IPackageManager;
69import android.content.pm.InstrumentationInfo;
Dan Egnor66c40e72010-01-26 16:23:11 -080070import android.content.pm.PackageInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080071import android.content.pm.PackageManager;
Dianne Hackborn2af632f2009-07-08 14:56:37 -070072import android.content.pm.PathPermission;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080073import android.content.pm.ProviderInfo;
74import android.content.pm.ResolveInfo;
75import android.content.pm.ServiceInfo;
Dianne Hackborn860755f2010-06-03 18:47:52 -070076import android.content.pm.PackageManager.NameNotFoundException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080077import android.content.res.Configuration;
78import android.graphics.Bitmap;
Robert Greenwalt434203a2010-10-11 16:00:27 -070079import android.net.Proxy;
80import android.net.ProxyProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080081import android.net.Uri;
82import android.os.Binder;
Dan Egnor60d87622009-12-16 16:32:58 -080083import android.os.Build;
Dan Egnor42471dd2010-01-07 17:25:22 -080084import android.os.Bundle;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070085import android.os.Debug;
Dan Egnor60d87622009-12-16 16:32:58 -080086import android.os.DropBoxManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080087import android.os.Environment;
Dan Egnor42471dd2010-01-07 17:25:22 -080088import android.os.FileObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080089import android.os.FileUtils;
90import android.os.Handler;
91import android.os.IBinder;
92import android.os.IPermissionController;
93import android.os.Looper;
94import android.os.Message;
95import android.os.Parcel;
96import android.os.ParcelFileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080097import android.os.Process;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070098import android.os.RemoteCallbackList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099import android.os.RemoteException;
100import android.os.ServiceManager;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -0700101import android.os.StrictMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102import android.os.SystemClock;
103import android.os.SystemProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800104import android.provider.Settings;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800105import android.util.Config;
106import android.util.EventLog;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800107import android.util.Slog;
Joe Onorato5d3bea62010-03-01 13:44:29 -0800108import android.util.Log;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800109import android.util.PrintWriterPrinter;
110import android.util.SparseArray;
Dianne Hackborn1ebccf52010-08-15 13:04:34 -0700111import android.util.TimeUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800112import android.view.Gravity;
113import android.view.LayoutInflater;
114import android.view.View;
115import android.view.WindowManager;
116import android.view.WindowManagerPolicy;
117
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700118import java.io.BufferedInputStream;
119import java.io.BufferedOutputStream;
120import java.io.DataInputStream;
121import java.io.DataOutputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800122import java.io.File;
123import java.io.FileDescriptor;
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700124import java.io.FileInputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800125import java.io.FileNotFoundException;
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700126import java.io.FileOutputStream;
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200127import java.io.IOException;
Dan Egnora455d192010-03-12 08:52:28 -0800128import java.io.InputStreamReader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800129import java.io.PrintWriter;
130import java.lang.IllegalStateException;
131import java.lang.ref.WeakReference;
132import java.util.ArrayList;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700133import java.util.Collections;
134import java.util.Comparator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800135import java.util.HashMap;
136import java.util.HashSet;
137import java.util.Iterator;
138import java.util.List;
139import java.util.Locale;
140import java.util.Map;
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -0700141import java.util.Set;
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700142import java.util.concurrent.atomic.AtomicBoolean;
143import java.util.concurrent.atomic.AtomicLong;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800144
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700145public final class ActivityManagerService extends ActivityManagerNative
146 implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800147 static final String TAG = "ActivityManager";
148 static final boolean DEBUG = false;
149 static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
150 static final boolean DEBUG_SWITCH = localLOGV || false;
151 static final boolean DEBUG_TASKS = localLOGV || false;
152 static final boolean DEBUG_PAUSE = localLOGV || false;
153 static final boolean DEBUG_OOM_ADJ = localLOGV || false;
154 static final boolean DEBUG_TRANSITION = localLOGV || false;
155 static final boolean DEBUG_BROADCAST = localLOGV || false;
Dianne Hackborn82f3f002009-06-16 18:49:05 -0700156 static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800157 static final boolean DEBUG_SERVICE = localLOGV || false;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700158 static final boolean DEBUG_SERVICE_EXECUTING = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800159 static final boolean DEBUG_VISBILITY = localLOGV || false;
160 static final boolean DEBUG_PROCESSES = localLOGV || false;
Dianne Hackborna1e989b2009-09-01 19:54:29 -0700161 static final boolean DEBUG_PROVIDER = localLOGV || false;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800162 static final boolean DEBUG_URI_PERMISSION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800163 static final boolean DEBUG_USER_LEAVING = localLOGV || false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700164 static final boolean DEBUG_RESULTS = localLOGV || false;
Christopher Tate436344a2009-09-30 16:17:37 -0700165 static final boolean DEBUG_BACKUP = localLOGV || false;
Dianne Hackborndc6b6352009-09-30 14:20:09 -0700166 static final boolean DEBUG_CONFIGURATION = localLOGV || false;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700167 static final boolean DEBUG_POWER = localLOGV || false;
168 static final boolean DEBUG_POWER_QUICK = DEBUG_POWER || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800169 static final boolean VALIDATE_TOKENS = false;
170 static final boolean SHOW_ACTIVITY_START_TIME = true;
171
172 // Control over CPU and battery monitoring.
173 static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes.
174 static final boolean MONITOR_CPU_USAGE = true;
175 static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds.
176 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample.
177 static final boolean MONITOR_THREAD_CPU_USAGE = false;
178
Dianne Hackborn1655be42009-05-08 14:29:01 -0700179 // The flags that are set for all calls we make to the package manager.
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700180 static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
Dianne Hackborn1655be42009-05-08 14:29:01 -0700181
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800182 private static final String SYSTEM_SECURE = "ro.secure";
Dianne Hackbornf02e57b2011-03-01 22:21:04 -0800183 private static final String SYSTEM_DEBUGGABLE = "ro.debuggable";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800184
185 // This is the maximum number of application processes we would like
186 // to have running. Due to the asynchronous nature of things, we can
187 // temporarily go beyond this limit.
188 static final int MAX_PROCESSES = 2;
189
190 // Set to false to leave processes running indefinitely, relying on
191 // the kernel killing them as resources are required.
192 static final boolean ENFORCE_PROCESS_LIMIT = false;
193
194 // This is the maximum number of activities that we would like to have
195 // running at a given time.
196 static final int MAX_ACTIVITIES = 20;
197
198 // Maximum number of recent tasks that we can remember.
199 static final int MAX_RECENT_TASKS = 20;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700200
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700201 // Amount of time after a call to stopAppSwitches() during which we will
202 // prevent further untrusted switches from happening.
203 static final long APP_SWITCH_DELAY_TIME = 5*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800204
205 // How long we wait for a launched process to attach to the activity manager
206 // before we decide it's never going to come up for real.
207 static final int PROC_START_TIMEOUT = 10*1000;
208
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800209 // How long to wait after going idle before forcing apps to GC.
210 static final int GC_TIMEOUT = 5*1000;
211
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700212 // The minimum amount of time between successive GC requests for a process.
213 static final int GC_MIN_INTERVAL = 60*1000;
214
Dianne Hackborn287952c2010-09-22 22:34:31 -0700215 // The rate at which we check for apps using excessive power -- 15 mins.
216 static final int POWER_CHECK_DELAY = (DEBUG_POWER_QUICK ? 2 : 15) * 60*1000;
217
218 // The minimum sample duration we will allow before deciding we have
219 // enough data on wake locks to start killing things.
220 static final int WAKE_LOCK_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
221
222 // The minimum sample duration we will allow before deciding we have
223 // enough data on CPU usage to start killing things.
224 static final int CPU_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700225
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800226 // How long we allow a receiver to run before giving up on it.
227 static final int BROADCAST_TIMEOUT = 10*1000;
228
229 // How long we wait for a service to finish executing.
230 static final int SERVICE_TIMEOUT = 20*1000;
231
232 // How long a service needs to be running until restarting its process
233 // is no longer considered to be a relaunch of the service.
234 static final int SERVICE_RESTART_DURATION = 5*1000;
235
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700236 // How long a service needs to be running until it will start back at
237 // SERVICE_RESTART_DURATION after being killed.
238 static final int SERVICE_RESET_RUN_DURATION = 60*1000;
239
240 // Multiplying factor to increase restart duration time by, for each time
241 // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
242 static final int SERVICE_RESTART_DURATION_FACTOR = 4;
243
244 // The minimum amount of time between restarting services that we allow.
245 // That is, when multiple services are restarting, we won't allow each
246 // to restart less than this amount of time from the last one.
247 static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
248
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800249 // Maximum amount of time for there to be no activity on a service before
250 // we consider it non-essential and allow its process to go on the
251 // LRU background list.
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700252 static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800253
254 // How long we wait until we timeout on key dispatching.
255 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
256
257 // The minimum time we allow between crashes, for us to consider this
258 // application to be bad and stop and its services and reject broadcasts.
259 static final int MIN_CRASH_INTERVAL = 60*1000;
260
261 // How long we wait until we timeout on key dispatching during instrumentation.
262 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
263
264 // OOM adjustments for processes in various states:
265
266 // This is a process without anything currently running in it. Definitely
267 // the first to go! Value set in system/rootdir/init.rc on startup.
268 // This value is initalized in the constructor, careful when refering to
269 // this static variable externally.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800270 static final int EMPTY_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800271
272 // This is a process only hosting activities that are not visible,
273 // so it can be killed without any disruption. Value set in
274 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800275 static final int HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800276 static int HIDDEN_APP_MIN_ADJ;
277
The Android Open Source Project4df24232009-03-05 14:34:35 -0800278 // This is a process holding the home application -- we want to try
279 // avoiding killing it, even if it would normally be in the background,
280 // because the user interacts with it so much.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800281 static final int HOME_APP_ADJ;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800282
Christopher Tate6fa95972009-06-05 18:43:55 -0700283 // This is a process currently hosting a backup operation. Killing it
284 // is not entirely fatal but is generally a bad idea.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800285 static final int BACKUP_APP_ADJ;
Christopher Tate6fa95972009-06-05 18:43:55 -0700286
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800287 // This is a process holding a secondary server -- killing it will not
288 // have much of an impact as far as the user is concerned. Value set in
289 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800290 static final int SECONDARY_SERVER_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800291
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700292 // This is a process with a heavy-weight application. It is in the
293 // background, but we want to try to avoid killing it. Value set in
294 // system/rootdir/init.rc on startup.
295 static final int HEAVY_WEIGHT_APP_ADJ;
296
297 // This is a process only hosting components that are perceptible to the
298 // user, and we really want to avoid killing them, but they are not
299 // immediately visible. An example is background music playback. Value set in
300 // system/rootdir/init.rc on startup.
301 static final int PERCEPTIBLE_APP_ADJ;
302
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800303 // This is a process only hosting activities that are visible to the
304 // user, so we'd prefer they don't disappear. Value set in
305 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800306 static final int VISIBLE_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800307
308 // This is the process running the current foreground app. We'd really
309 // rather not kill it! Value set in system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800310 static final int FOREGROUND_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800311
312 // This is a process running a core server, such as telephony. Definitely
313 // don't want to kill it, but doing so is not completely fatal.
314 static final int CORE_SERVER_ADJ = -12;
315
316 // The system process runs at the default adjustment.
317 static final int SYSTEM_ADJ = -16;
318
319 // Memory pages are 4K.
320 static final int PAGE_SIZE = 4*1024;
321
322 // Corresponding memory levels for above adjustments.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800323 static final int EMPTY_APP_MEM;
324 static final int HIDDEN_APP_MEM;
325 static final int HOME_APP_MEM;
326 static final int BACKUP_APP_MEM;
327 static final int SECONDARY_SERVER_MEM;
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700328 static final int HEAVY_WEIGHT_APP_MEM;
329 static final int PERCEPTIBLE_APP_MEM;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800330 static final int VISIBLE_APP_MEM;
331 static final int FOREGROUND_APP_MEM;
332
333 // The minimum number of hidden apps we want to be able to keep around,
334 // without empty apps being able to push them out of memory.
335 static final int MIN_HIDDEN_APPS = 2;
336
Dianne Hackborn8633e682010-04-22 16:03:41 -0700337 // The maximum number of hidden processes we will keep around before
338 // killing them; this is just a control to not let us go too crazy with
339 // keeping around processes on devices with large amounts of RAM.
340 static final int MAX_HIDDEN_APPS = 15;
341
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800342 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700343 // been idle for less than 15 seconds.
344 static final long CONTENT_APP_IDLE_OFFSET = 15*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800345
346 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700347 // been idle for less than 120 seconds.
348 static final long EMPTY_APP_IDLE_OFFSET = 120*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800349
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700350 static int getIntProp(String name, boolean allowZero) {
351 String str = SystemProperties.get(name);
352 if (str == null) {
353 throw new IllegalArgumentException("Property not defined: " + name);
354 }
355 int val = Integer.valueOf(str);
356 if (val == 0 && !allowZero) {
357 throw new IllegalArgumentException("Property must not be zero: " + name);
358 }
359 return val;
360 }
361
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800362 static {
363 // These values are set in system/rootdir/init.rc on startup.
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700364 FOREGROUND_APP_ADJ = getIntProp("ro.FOREGROUND_APP_ADJ", true);
365 VISIBLE_APP_ADJ = getIntProp("ro.VISIBLE_APP_ADJ", true);
366 PERCEPTIBLE_APP_ADJ = getIntProp("ro.PERCEPTIBLE_APP_ADJ", true);
367 HEAVY_WEIGHT_APP_ADJ = getIntProp("ro.HEAVY_WEIGHT_APP_ADJ", true);
368 SECONDARY_SERVER_ADJ = getIntProp("ro.SECONDARY_SERVER_ADJ", true);
369 BACKUP_APP_ADJ = getIntProp("ro.BACKUP_APP_ADJ", true);
370 HOME_APP_ADJ = getIntProp("ro.HOME_APP_ADJ", true);
371 HIDDEN_APP_MIN_ADJ = getIntProp("ro.HIDDEN_APP_MIN_ADJ", true);
372 EMPTY_APP_ADJ = getIntProp("ro.EMPTY_APP_ADJ", true);
373 // These days we use the last empty slot for hidden apps as well.
374 HIDDEN_APP_MAX_ADJ = EMPTY_APP_ADJ;
375 FOREGROUND_APP_MEM = getIntProp("ro.FOREGROUND_APP_MEM", false)*PAGE_SIZE;
376 VISIBLE_APP_MEM = getIntProp("ro.VISIBLE_APP_MEM", false)*PAGE_SIZE;
377 PERCEPTIBLE_APP_MEM = getIntProp("ro.PERCEPTIBLE_APP_MEM", false)*PAGE_SIZE;
378 HEAVY_WEIGHT_APP_MEM = getIntProp("ro.HEAVY_WEIGHT_APP_MEM", false)*PAGE_SIZE;
379 SECONDARY_SERVER_MEM = getIntProp("ro.SECONDARY_SERVER_MEM", false)*PAGE_SIZE;
380 BACKUP_APP_MEM = getIntProp("ro.BACKUP_APP_MEM", false)*PAGE_SIZE;
381 HOME_APP_MEM = getIntProp("ro.HOME_APP_MEM", false)*PAGE_SIZE;
382 HIDDEN_APP_MEM = getIntProp("ro.HIDDEN_APP_MEM", false)*PAGE_SIZE;
383 EMPTY_APP_MEM = getIntProp("ro.EMPTY_APP_MEM", false)*PAGE_SIZE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800384 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800385
Dan Egnor42471dd2010-01-07 17:25:22 -0800386 static final int MY_PID = Process.myPid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800387
388 static final String[] EMPTY_STRING_ARRAY = new String[0];
389
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700390 public ActivityStack mMainStack;
391
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800392 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700393 * Description of a request to start a new activity, which has been held
394 * due to app switches being disabled.
395 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700396 static class PendingActivityLaunch {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700397 ActivityRecord r;
398 ActivityRecord sourceRecord;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700399 Uri[] grantedUriPermissions;
400 int grantedMode;
401 boolean onlyIfNeeded;
402 }
403
404 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
405 = new ArrayList<PendingActivityLaunch>();
406
407 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800408 * List of all active broadcasts that are to be executed immediately
409 * (without waiting for another broadcast to finish). Currently this only
410 * contains broadcasts to registered receivers, to avoid spinning up
411 * a bunch of processes to execute IntentReceiver components.
412 */
413 final ArrayList<BroadcastRecord> mParallelBroadcasts
414 = new ArrayList<BroadcastRecord>();
415
416 /**
417 * List of all active broadcasts that are to be executed one at a time.
418 * The object at the top of the list is the currently activity broadcasts;
419 * those after it are waiting for the top to finish..
420 */
421 final ArrayList<BroadcastRecord> mOrderedBroadcasts
422 = new ArrayList<BroadcastRecord>();
423
424 /**
Dianne Hackborn12527f92009-11-11 17:39:50 -0800425 * Historical data of past broadcasts, for debugging.
426 */
427 static final int MAX_BROADCAST_HISTORY = 100;
428 final BroadcastRecord[] mBroadcastHistory
429 = new BroadcastRecord[MAX_BROADCAST_HISTORY];
430
431 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800432 * Set when we current have a BROADCAST_INTENT_MSG in flight.
433 */
434 boolean mBroadcastsScheduled = false;
435
436 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800437 * Activity we have told the window manager to have key focus.
438 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700439 ActivityRecord mFocusedActivity = null;
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700440 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800441 * List of intents that were used to start the most recent tasks.
442 */
443 final ArrayList<TaskRecord> mRecentTasks
444 = new ArrayList<TaskRecord>();
445
446 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800447 * All of the applications we currently have running organized by name.
448 * The keys are strings of the application package name (as
449 * returned by the package manager), and the keys are ApplicationRecord
450 * objects.
451 */
452 final ProcessMap<ProcessRecord> mProcessNames
453 = new ProcessMap<ProcessRecord>();
454
455 /**
Dianne Hackborn860755f2010-06-03 18:47:52 -0700456 * The currently running heavy-weight process, if any.
457 */
458 ProcessRecord mHeavyWeightProcess = null;
459
460 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800461 * The last time that various processes have crashed.
462 */
463 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
464
465 /**
466 * Set of applications that we consider to be bad, and will reject
467 * incoming broadcasts from (which the user has no control over).
468 * Processes are added to this set when they have crashed twice within
469 * a minimum amount of time; they are removed from it when they are
470 * later restarted (hopefully due to some user action). The value is the
471 * time it was added to the list.
472 */
473 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
474
475 /**
476 * All of the processes we currently have running organized by pid.
477 * The keys are the pid running the application.
478 *
479 * <p>NOTE: This object is protected by its own lock, NOT the global
480 * activity manager lock!
481 */
482 final SparseArray<ProcessRecord> mPidsSelfLocked
483 = new SparseArray<ProcessRecord>();
484
485 /**
486 * All of the processes that have been forced to be foreground. The key
487 * is the pid of the caller who requested it (we hold a death
488 * link on it).
489 */
490 abstract class ForegroundToken implements IBinder.DeathRecipient {
491 int pid;
492 IBinder token;
493 }
494 final SparseArray<ForegroundToken> mForegroundProcesses
495 = new SparseArray<ForegroundToken>();
496
497 /**
498 * List of records for processes that someone had tried to start before the
499 * system was ready. We don't start them at that point, but ensure they
500 * are started by the time booting is complete.
501 */
502 final ArrayList<ProcessRecord> mProcessesOnHold
503 = new ArrayList<ProcessRecord>();
504
505 /**
506 * List of records for processes that we have started and are waiting
507 * for them to call back. This is really only needed when running in
508 * single processes mode, in which case we do not have a unique pid for
509 * each process.
510 */
511 final ArrayList<ProcessRecord> mStartingProcesses
512 = new ArrayList<ProcessRecord>();
513
514 /**
515 * List of persistent applications that are in the process
516 * of being started.
517 */
518 final ArrayList<ProcessRecord> mPersistentStartingProcesses
519 = new ArrayList<ProcessRecord>();
520
521 /**
522 * Processes that are being forcibly torn down.
523 */
524 final ArrayList<ProcessRecord> mRemovedProcesses
525 = new ArrayList<ProcessRecord>();
526
527 /**
528 * List of running applications, sorted by recent usage.
529 * The first entry in the list is the least recently used.
530 * It contains ApplicationRecord objects. This list does NOT include
531 * any persistent application records (since we never want to exit them).
532 */
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800533 final ArrayList<ProcessRecord> mLruProcesses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800534 = new ArrayList<ProcessRecord>();
535
536 /**
537 * List of processes that should gc as soon as things are idle.
538 */
539 final ArrayList<ProcessRecord> mProcessesToGc
540 = new ArrayList<ProcessRecord>();
541
542 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -0800543 * This is the process holding what we currently consider to be
544 * the "home" activity.
545 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700546 ProcessRecord mHomeProcess;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800547
548 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800549 * Set of PendingResultRecord objects that are currently active.
550 */
551 final HashSet mPendingResultRecords = new HashSet();
552
553 /**
554 * Set of IntentSenderRecord objects that are currently active.
555 */
556 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
557 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
558
559 /**
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -0800560 * Fingerprints (hashCode()) of stack traces that we've
Brad Fitzpatrick143666f2010-06-14 12:40:21 -0700561 * already logged DropBox entries for. Guarded by itself. If
562 * something (rogue user app) forces this over
563 * MAX_DUP_SUPPRESSED_STACKS entries, the contents are cleared.
564 */
565 private final HashSet<Integer> mAlreadyLoggedViolatedStacks = new HashSet<Integer>();
566 private static final int MAX_DUP_SUPPRESSED_STACKS = 5000;
567
568 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -0700569 * Strict Mode background batched logging state.
570 *
571 * The string buffer is guarded by itself, and its lock is also
572 * used to determine if another batched write is already
573 * in-flight.
574 */
575 private final StringBuilder mStrictModeBuffer = new StringBuilder();
576
577 /**
Jeff Brown4d94a762010-09-23 11:33:28 -0700578 * True if we have a pending unexpired BROADCAST_TIMEOUT_MSG posted to our handler.
579 */
580 private boolean mPendingBroadcastTimeoutMessage;
581
582 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800583 * Intent broadcast that we have tried to start, but are
584 * waiting for its application's process to be created. We only
585 * need one (instead of a list) because we always process broadcasts
586 * one at a time, so no others can be started while waiting for this
587 * one.
588 */
589 BroadcastRecord mPendingBroadcast = null;
590
591 /**
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700592 * The receiver index that is pending, to restart the broadcast if needed.
593 */
594 int mPendingBroadcastRecvIndex;
595
596 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800597 * Keeps track of all IIntentReceivers that have been registered for
598 * broadcasts. Hash keys are the receiver IBinder, hash value is
599 * a ReceiverList.
600 */
601 final HashMap mRegisteredReceivers = new HashMap();
602
603 /**
604 * Resolver for broadcast intents to registered receivers.
605 * Holds BroadcastFilter (subclass of IntentFilter).
606 */
607 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
608 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
609 @Override
610 protected boolean allowFilterResult(
611 BroadcastFilter filter, List<BroadcastFilter> dest) {
612 IBinder target = filter.receiverList.receiver.asBinder();
613 for (int i=dest.size()-1; i>=0; i--) {
614 if (dest.get(i).receiverList.receiver.asBinder() == target) {
615 return false;
616 }
617 }
618 return true;
619 }
620 };
621
622 /**
623 * State of all active sticky broadcasts. Keys are the action of the
624 * sticky Intent, values are an ArrayList of all broadcasted intents with
625 * that action (which should usually be one).
626 */
627 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
628 new HashMap<String, ArrayList<Intent>>();
629
630 /**
631 * All currently running services.
632 */
633 final HashMap<ComponentName, ServiceRecord> mServices =
634 new HashMap<ComponentName, ServiceRecord>();
635
636 /**
637 * All currently running services indexed by the Intent used to start them.
638 */
639 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
640 new HashMap<Intent.FilterComparison, ServiceRecord>();
641
642 /**
643 * All currently bound service connections. Keys are the IBinder of
644 * the client's IServiceConnection.
645 */
Dianne Hackborn43d9ac82010-08-25 15:06:25 -0700646 final HashMap<IBinder, ArrayList<ConnectionRecord>> mServiceConnections
647 = new HashMap<IBinder, ArrayList<ConnectionRecord>>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800648
649 /**
650 * List of services that we have been asked to start,
651 * but haven't yet been able to. It is used to hold start requests
652 * while waiting for their corresponding application thread to get
653 * going.
654 */
655 final ArrayList<ServiceRecord> mPendingServices
656 = new ArrayList<ServiceRecord>();
657
658 /**
659 * List of services that are scheduled to restart following a crash.
660 */
661 final ArrayList<ServiceRecord> mRestartingServices
662 = new ArrayList<ServiceRecord>();
663
664 /**
665 * List of services that are in the process of being stopped.
666 */
667 final ArrayList<ServiceRecord> mStoppingServices
668 = new ArrayList<ServiceRecord>();
669
670 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700671 * Backup/restore process management
672 */
673 String mBackupAppName = null;
674 BackupRecord mBackupTarget = null;
675
676 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800677 * List of PendingThumbnailsRecord objects of clients who are still
678 * waiting to receive all of the thumbnails for a task.
679 */
680 final ArrayList mPendingThumbnails = new ArrayList();
681
682 /**
683 * List of HistoryRecord objects that have been finished and must
684 * still report back to a pending thumbnail receiver.
685 */
686 final ArrayList mCancelledThumbnails = new ArrayList();
687
688 /**
689 * All of the currently running global content providers. Keys are a
690 * string containing the provider name and values are a
691 * ContentProviderRecord object containing the data about it. Note
692 * that a single provider may be published under multiple names, so
693 * there may be multiple entries here for a single one in mProvidersByClass.
694 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700695 final HashMap<String, ContentProviderRecord> mProvidersByName
696 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800697
698 /**
699 * All of the currently running global content providers. Keys are a
700 * string containing the provider's implementation class and values are a
701 * ContentProviderRecord object containing the data about it.
702 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700703 final HashMap<String, ContentProviderRecord> mProvidersByClass
704 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800705
706 /**
707 * List of content providers who have clients waiting for them. The
708 * application is currently being launched and the provider will be
709 * removed from this list once it is published.
710 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700711 final ArrayList<ContentProviderRecord> mLaunchingProviders
712 = new ArrayList<ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800713
714 /**
715 * Global set of specific Uri permissions that have been granted.
716 */
717 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
718 = new SparseArray<HashMap<Uri, UriPermission>>();
719
Svetoslav Ganov54d068e2011-03-02 12:58:40 -0800720 CoreSettingsObserver mCoreSettingsObserver;
721
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800722 /**
723 * Thread-local storage used to carry caller permissions over through
724 * indirect content-provider access.
725 * @see #ActivityManagerService.openContentUri()
726 */
727 private class Identity {
728 public int pid;
729 public int uid;
730
731 Identity(int _pid, int _uid) {
732 pid = _pid;
733 uid = _uid;
734 }
735 }
736 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
737
738 /**
739 * All information we have collected about the runtime performance of
740 * any user id that can impact battery performance.
741 */
742 final BatteryStatsService mBatteryStatsService;
743
744 /**
745 * information about component usage
746 */
747 final UsageStatsService mUsageStatsService;
748
749 /**
750 * Current configuration information. HistoryRecord objects are given
751 * a reference to this object to indicate which configuration they are
752 * currently running in, so this object must be kept immutable.
753 */
754 Configuration mConfiguration = new Configuration();
755
756 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800757 * Current sequencing integer of the configuration, for skipping old
758 * configurations.
759 */
760 int mConfigurationSeq = 0;
761
762 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700763 * Hardware-reported OpenGLES version.
764 */
765 final int GL_ES_VERSION;
766
767 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800768 * List of initialization arguments to pass to all processes when binding applications to them.
769 * For example, references to the commonly used services.
770 */
771 HashMap<String, IBinder> mAppBindArgs;
772
773 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700774 * Temporary to avoid allocations. Protected by main lock.
775 */
776 final StringBuilder mStringBuilder = new StringBuilder(256);
777
778 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800779 * Used to control how we initialize the service.
780 */
781 boolean mStartRunning = false;
782 ComponentName mTopComponent;
783 String mTopAction;
784 String mTopData;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700785 boolean mProcessesReady = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800786 boolean mSystemReady = false;
787 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700788 boolean mWaitingUpdate = false;
789 boolean mDidUpdate = false;
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700790 boolean mOnBattery = false;
Dianne Hackborn0dad3642010-09-09 21:25:35 -0700791 boolean mLaunchWarningShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800792
793 Context mContext;
794
795 int mFactoryTest;
796
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700797 boolean mCheckedForSetup;
798
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800799 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700800 * The time at which we will allow normal application switches again,
801 * after a call to {@link #stopAppSwitches()}.
802 */
803 long mAppSwitchesAllowedTime;
804
805 /**
806 * This is set to true after the first switch after mAppSwitchesAllowedTime
807 * is set; any switches after that will clear the time.
808 */
809 boolean mDidAppSwitch;
810
811 /**
Dianne Hackborn287952c2010-09-22 22:34:31 -0700812 * Last time (in realtime) at which we checked for power usage.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700813 */
Dianne Hackborn287952c2010-09-22 22:34:31 -0700814 long mLastPowerCheckRealtime;
815
816 /**
817 * Last time (in uptime) at which we checked for power usage.
818 */
819 long mLastPowerCheckUptime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700820
821 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800822 * Set while we are wanting to sleep, to prevent any
823 * activities from being started/resumed.
824 */
825 boolean mSleeping = false;
826
827 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700828 * Set if we are shutting down the system, similar to sleeping.
829 */
830 boolean mShuttingDown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800831
832 /**
833 * Task identifier that activities are currently being started
834 * in. Incremented each time a new task is created.
835 * todo: Replace this with a TokenSpace class that generates non-repeating
836 * integers that won't wrap.
837 */
838 int mCurTask = 1;
839
840 /**
841 * Current sequence id for oom_adj computation traversal.
842 */
843 int mAdjSeq = 0;
844
845 /**
Dianne Hackborn906497c2010-05-10 15:57:38 -0700846 * Current sequence id for process LRU updating.
847 */
848 int mLruSeq = 0;
849
850 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800851 * Set to true if the ANDROID_SIMPLE_PROCESS_MANAGEMENT envvar
852 * is set, indicating the user wants processes started in such a way
853 * that they can use ANDROID_PROCESS_WRAPPER and know what will be
854 * running in each process (thus no pre-initialized process, etc).
855 */
856 boolean mSimpleProcessManagement = false;
857
858 /**
859 * System monitoring: number of processes that died since the last
860 * N procs were started.
861 */
862 int[] mProcDeaths = new int[20];
863
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700864 /**
865 * This is set if we had to do a delayed dexopt of an app before launching
866 * it, to increasing the ANR timeouts in that case.
867 */
868 boolean mDidDexOpt;
869
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800870 String mDebugApp = null;
871 boolean mWaitForDebugger = false;
872 boolean mDebugTransient = false;
873 String mOrigDebugApp = null;
874 boolean mOrigWaitForDebugger = false;
875 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700876 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800877
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700878 final RemoteCallbackList<IActivityWatcher> mWatchers
879 = new RemoteCallbackList<IActivityWatcher>();
880
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800881 /**
882 * Callback of last caller to {@link #requestPss}.
883 */
884 Runnable mRequestPssCallback;
885
886 /**
887 * Remaining processes for which we are waiting results from the last
888 * call to {@link #requestPss}.
889 */
890 final ArrayList<ProcessRecord> mRequestPssList
891 = new ArrayList<ProcessRecord>();
892
893 /**
894 * Runtime statistics collection thread. This object's lock is used to
895 * protect all related state.
896 */
897 final Thread mProcessStatsThread;
898
899 /**
900 * Used to collect process stats when showing not responding dialog.
901 * Protected by mProcessStatsThread.
902 */
903 final ProcessStats mProcessStats = new ProcessStats(
904 MONITOR_THREAD_CPU_USAGE);
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700905 final AtomicLong mLastCpuTime = new AtomicLong(0);
906 final AtomicBoolean mProcessStatsMutexFree = new AtomicBoolean(true);
907
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800908 long mLastWriteTime = 0;
909
910 /**
911 * Set to true after the system has finished booting.
912 */
913 boolean mBooted = false;
914
915 int mProcessLimit = 0;
916
917 WindowManagerService mWindowManager;
918
919 static ActivityManagerService mSelf;
920 static ActivityThread mSystemThread;
921
922 private final class AppDeathRecipient implements IBinder.DeathRecipient {
923 final ProcessRecord mApp;
924 final int mPid;
925 final IApplicationThread mAppThread;
926
927 AppDeathRecipient(ProcessRecord app, int pid,
928 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800929 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800930 TAG, "New death recipient " + this
931 + " for thread " + thread.asBinder());
932 mApp = app;
933 mPid = pid;
934 mAppThread = thread;
935 }
936
937 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800938 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800939 TAG, "Death received in " + this
940 + " for thread " + mAppThread.asBinder());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800941 synchronized(ActivityManagerService.this) {
942 appDiedLocked(mApp, mPid, mAppThread);
943 }
944 }
945 }
946
947 static final int SHOW_ERROR_MSG = 1;
948 static final int SHOW_NOT_RESPONDING_MSG = 2;
949 static final int SHOW_FACTORY_ERROR_MSG = 3;
950 static final int UPDATE_CONFIGURATION_MSG = 4;
951 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
952 static final int WAIT_FOR_DEBUGGER_MSG = 6;
953 static final int BROADCAST_INTENT_MSG = 7;
954 static final int BROADCAST_TIMEOUT_MSG = 8;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800955 static final int SERVICE_TIMEOUT_MSG = 12;
956 static final int UPDATE_TIME_ZONE = 13;
957 static final int SHOW_UID_ERROR_MSG = 14;
958 static final int IM_FEELING_LUCKY_MSG = 15;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800959 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700960 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -0700961 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800962 static final int FINALIZE_PENDING_INTENT_MSG = 23;
Dianne Hackborn860755f2010-06-03 18:47:52 -0700963 static final int POST_HEAVY_NOTIFICATION_MSG = 24;
964 static final int CANCEL_HEAVY_NOTIFICATION_MSG = 25;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700965 static final int SHOW_STRICT_MODE_VIOLATION_MSG = 26;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700966 static final int CHECK_EXCESSIVE_WAKE_LOCKS_MSG = 27;
Robert Greenwalt03595d02010-11-02 14:08:23 -0700967 static final int CLEAR_DNS_CACHE = 28;
Robert Greenwalt434203a2010-10-11 16:00:27 -0700968 static final int UPDATE_HTTP_PROXY = 29;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800969
970 AlertDialog mUidAlert;
971
972 final Handler mHandler = new Handler() {
973 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800974 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800975 //}
976
977 public void handleMessage(Message msg) {
978 switch (msg.what) {
979 case SHOW_ERROR_MSG: {
980 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800981 synchronized (ActivityManagerService.this) {
982 ProcessRecord proc = (ProcessRecord)data.get("app");
983 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800984 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800985 return;
986 }
987 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -0700988 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -0800989 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800990 d.show();
991 proc.crashDialog = d;
992 } else {
993 // The device is asleep, so just pretend that the user
994 // saw a crash dialog and hit "force quit".
995 res.set(0);
996 }
997 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700998
999 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001000 } break;
1001 case SHOW_NOT_RESPONDING_MSG: {
1002 synchronized (ActivityManagerService.this) {
1003 HashMap data = (HashMap) msg.obj;
1004 ProcessRecord proc = (ProcessRecord)data.get("app");
1005 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001006 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001007 return;
1008 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001009
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001010 Intent intent = new Intent("android.intent.action.ANR");
1011 if (!mProcessesReady) {
1012 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
1013 }
1014 broadcastIntentLocked(null, null, intent,
The Android Open Source Project4df24232009-03-05 14:34:35 -08001015 null, null, 0, null, null, null,
1016 false, false, MY_PID, Process.SYSTEM_UID);
1017
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001018 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001019 mContext, proc, (ActivityRecord)data.get("activity"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001020 d.show();
1021 proc.anrDialog = d;
1022 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001023
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001024 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001025 } break;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001026 case SHOW_STRICT_MODE_VIOLATION_MSG: {
1027 HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
1028 synchronized (ActivityManagerService.this) {
1029 ProcessRecord proc = (ProcessRecord) data.get("app");
1030 if (proc == null) {
1031 Slog.e(TAG, "App not found when showing strict mode dialog.");
1032 break;
1033 }
1034 if (proc.crashDialog != null) {
1035 Slog.e(TAG, "App already has strict mode dialog: " + proc);
1036 return;
1037 }
1038 AppErrorResult res = (AppErrorResult) data.get("result");
1039 if (!mSleeping && !mShuttingDown) {
1040 Dialog d = new StrictModeViolationDialog(mContext, res, proc);
1041 d.show();
1042 proc.crashDialog = d;
1043 } else {
1044 // The device is asleep, so just pretend that the user
1045 // saw a crash dialog and hit "force quit".
1046 res.set(0);
1047 }
1048 }
1049 ensureBootCompleted();
1050 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001051 case SHOW_FACTORY_ERROR_MSG: {
1052 Dialog d = new FactoryErrorDialog(
1053 mContext, msg.getData().getCharSequence("msg"));
1054 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001055 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001056 } break;
1057 case UPDATE_CONFIGURATION_MSG: {
1058 final ContentResolver resolver = mContext.getContentResolver();
1059 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1060 } break;
1061 case GC_BACKGROUND_PROCESSES_MSG: {
1062 synchronized (ActivityManagerService.this) {
1063 performAppGcsIfAppropriateLocked();
1064 }
1065 } break;
1066 case WAIT_FOR_DEBUGGER_MSG: {
1067 synchronized (ActivityManagerService.this) {
1068 ProcessRecord app = (ProcessRecord)msg.obj;
1069 if (msg.arg1 != 0) {
1070 if (!app.waitedForDebugger) {
1071 Dialog d = new AppWaitingForDebuggerDialog(
1072 ActivityManagerService.this,
1073 mContext, app);
1074 app.waitDialog = d;
1075 app.waitedForDebugger = true;
1076 d.show();
1077 }
1078 } else {
1079 if (app.waitDialog != null) {
1080 app.waitDialog.dismiss();
1081 app.waitDialog = null;
1082 }
1083 }
1084 }
1085 } break;
1086 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001087 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001088 TAG, "Received BROADCAST_INTENT_MSG");
1089 processNextBroadcast(true);
1090 } break;
1091 case BROADCAST_TIMEOUT_MSG: {
Jeff Brown4d94a762010-09-23 11:33:28 -07001092 synchronized (ActivityManagerService.this) {
1093 broadcastTimeoutLocked(true);
Jeff Hamiltonacf84742010-05-25 22:10:18 -05001094 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001095 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001096 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001097 if (mDidDexOpt) {
1098 mDidDexOpt = false;
1099 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1100 nmsg.obj = msg.obj;
1101 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1102 return;
1103 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001104 serviceTimeout((ProcessRecord)msg.obj);
1105 } break;
1106 case UPDATE_TIME_ZONE: {
1107 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001108 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1109 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001110 if (r.thread != null) {
1111 try {
1112 r.thread.updateTimeZone();
1113 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001114 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001115 }
1116 }
1117 }
1118 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001119 } break;
Robert Greenwalt03595d02010-11-02 14:08:23 -07001120 case CLEAR_DNS_CACHE: {
1121 synchronized (ActivityManagerService.this) {
1122 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1123 ProcessRecord r = mLruProcesses.get(i);
1124 if (r.thread != null) {
1125 try {
1126 r.thread.clearDnsCache();
1127 } catch (RemoteException ex) {
1128 Slog.w(TAG, "Failed to clear dns cache for: " + r.info.processName);
1129 }
1130 }
1131 }
1132 }
1133 } break;
Robert Greenwalt434203a2010-10-11 16:00:27 -07001134 case UPDATE_HTTP_PROXY: {
1135 ProxyProperties proxy = (ProxyProperties)msg.obj;
1136 String host = "";
1137 String port = "";
1138 String exclList = "";
1139 if (proxy != null) {
1140 host = proxy.getHost();
1141 port = Integer.toString(proxy.getPort());
1142 exclList = proxy.getExclusionList();
1143 }
1144 synchronized (ActivityManagerService.this) {
1145 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1146 ProcessRecord r = mLruProcesses.get(i);
1147 if (r.thread != null) {
1148 try {
1149 r.thread.setHttpProxy(host, port, exclList);
1150 } catch (RemoteException ex) {
1151 Slog.w(TAG, "Failed to update http proxy for: " +
1152 r.info.processName);
1153 }
1154 }
1155 }
1156 }
1157 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001158 case SHOW_UID_ERROR_MSG: {
1159 // XXX This is a temporary dialog, no need to localize.
1160 AlertDialog d = new BaseErrorDialog(mContext);
1161 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1162 d.setCancelable(false);
1163 d.setTitle("System UIDs Inconsistent");
1164 d.setMessage("UIDs on the system are inconsistent, you need to wipe your data partition or your device will be unstable.");
Christian Mehlmauer7664e202010-07-20 08:46:17 +02001165 d.setButton(DialogInterface.BUTTON_POSITIVE, "I'm Feeling Lucky",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001166 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1167 mUidAlert = d;
1168 d.show();
1169 } break;
1170 case IM_FEELING_LUCKY_MSG: {
1171 if (mUidAlert != null) {
1172 mUidAlert.dismiss();
1173 mUidAlert = null;
1174 }
1175 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001176 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001177 if (mDidDexOpt) {
1178 mDidDexOpt = false;
1179 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1180 nmsg.obj = msg.obj;
1181 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1182 return;
1183 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001184 ProcessRecord app = (ProcessRecord)msg.obj;
1185 synchronized (ActivityManagerService.this) {
1186 processStartTimedOutLocked(app);
1187 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001188 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001189 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1190 synchronized (ActivityManagerService.this) {
1191 doPendingActivityLaunchesLocked(true);
1192 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001193 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001194 case KILL_APPLICATION_MSG: {
1195 synchronized (ActivityManagerService.this) {
1196 int uid = msg.arg1;
1197 boolean restart = (msg.arg2 == 1);
1198 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001199 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001200 }
1201 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001202 case FINALIZE_PENDING_INTENT_MSG: {
1203 ((PendingIntentRecord)msg.obj).completeFinalize();
1204 } break;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001205 case POST_HEAVY_NOTIFICATION_MSG: {
1206 INotificationManager inm = NotificationManager.getService();
1207 if (inm == null) {
1208 return;
1209 }
1210
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001211 ActivityRecord root = (ActivityRecord)msg.obj;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001212 ProcessRecord process = root.app;
1213 if (process == null) {
1214 return;
1215 }
1216
1217 try {
1218 Context context = mContext.createPackageContext(process.info.packageName, 0);
1219 String text = mContext.getString(R.string.heavy_weight_notification,
1220 context.getApplicationInfo().loadLabel(context.getPackageManager()));
1221 Notification notification = new Notification();
1222 notification.icon = com.android.internal.R.drawable.stat_sys_adb; //context.getApplicationInfo().icon;
1223 notification.when = 0;
1224 notification.flags = Notification.FLAG_ONGOING_EVENT;
1225 notification.tickerText = text;
1226 notification.defaults = 0; // please be quiet
1227 notification.sound = null;
1228 notification.vibrate = null;
1229 notification.setLatestEventInfo(context, text,
1230 mContext.getText(R.string.heavy_weight_notification_detail),
1231 PendingIntent.getActivity(mContext, 0, root.intent,
1232 PendingIntent.FLAG_CANCEL_CURRENT));
1233
1234 try {
1235 int[] outId = new int[1];
1236 inm.enqueueNotification("android", R.string.heavy_weight_notification,
1237 notification, outId);
1238 } catch (RuntimeException e) {
1239 Slog.w(ActivityManagerService.TAG,
1240 "Error showing notification for heavy-weight app", e);
1241 } catch (RemoteException e) {
1242 }
1243 } catch (NameNotFoundException e) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07001244 Slog.w(TAG, "Unable to create context for heavy notification", e);
Dianne Hackborn860755f2010-06-03 18:47:52 -07001245 }
1246 } break;
1247 case CANCEL_HEAVY_NOTIFICATION_MSG: {
1248 INotificationManager inm = NotificationManager.getService();
1249 if (inm == null) {
1250 return;
1251 }
1252 try {
1253 inm.cancelNotification("android",
1254 R.string.heavy_weight_notification);
1255 } catch (RuntimeException e) {
1256 Slog.w(ActivityManagerService.TAG,
1257 "Error canceling notification for service", e);
1258 } catch (RemoteException e) {
1259 }
1260 } break;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001261 case CHECK_EXCESSIVE_WAKE_LOCKS_MSG: {
1262 synchronized (ActivityManagerService.this) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001263 checkExcessivePowerUsageLocked(true);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -07001264 removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001265 Message nmsg = obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
1266 sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001267 }
1268 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001269 }
1270 }
1271 };
1272
1273 public static void setSystemProcess() {
1274 try {
1275 ActivityManagerService m = mSelf;
1276
1277 ServiceManager.addService("activity", m);
1278 ServiceManager.addService("meminfo", new MemBinder(m));
1279 if (MONITOR_CPU_USAGE) {
1280 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1281 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001282 ServiceManager.addService("permission", new PermissionController(m));
1283
1284 ApplicationInfo info =
1285 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001286 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001287 mSystemThread.installSystemApplicationInfo(info);
1288
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001289 synchronized (mSelf) {
1290 ProcessRecord app = mSelf.newProcessRecordLocked(
1291 mSystemThread.getApplicationThread(), info,
1292 info.processName);
1293 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001294 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001295 app.maxAdj = SYSTEM_ADJ;
1296 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1297 synchronized (mSelf.mPidsSelfLocked) {
1298 mSelf.mPidsSelfLocked.put(app.pid, app);
1299 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001300 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001301 }
1302 } catch (PackageManager.NameNotFoundException e) {
1303 throw new RuntimeException(
1304 "Unable to find android system package", e);
1305 }
1306 }
1307
1308 public void setWindowManager(WindowManagerService wm) {
1309 mWindowManager = wm;
1310 }
1311
1312 public static final Context main(int factoryTest) {
1313 AThread thr = new AThread();
1314 thr.start();
1315
1316 synchronized (thr) {
1317 while (thr.mService == null) {
1318 try {
1319 thr.wait();
1320 } catch (InterruptedException e) {
1321 }
1322 }
1323 }
1324
1325 ActivityManagerService m = thr.mService;
1326 mSelf = m;
1327 ActivityThread at = ActivityThread.systemMain();
1328 mSystemThread = at;
1329 Context context = at.getSystemContext();
Dianne Hackborn247fe742011-01-08 17:25:57 -08001330 context.setTheme(android.R.style.Theme_Holo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001331 m.mContext = context;
1332 m.mFactoryTest = factoryTest;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001333 m.mMainStack = new ActivityStack(m, context, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001334
1335 m.mBatteryStatsService.publish(context);
1336 m.mUsageStatsService.publish(context);
1337
1338 synchronized (thr) {
1339 thr.mReady = true;
1340 thr.notifyAll();
1341 }
1342
1343 m.startRunning(null, null, null, null);
1344
1345 return context;
1346 }
1347
1348 public static ActivityManagerService self() {
1349 return mSelf;
1350 }
1351
1352 static class AThread extends Thread {
1353 ActivityManagerService mService;
1354 boolean mReady = false;
1355
1356 public AThread() {
1357 super("ActivityManager");
1358 }
1359
1360 public void run() {
1361 Looper.prepare();
1362
1363 android.os.Process.setThreadPriority(
1364 android.os.Process.THREAD_PRIORITY_FOREGROUND);
Christopher Tate160edb32010-06-30 17:46:30 -07001365 android.os.Process.setCanSelfBackground(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001366
1367 ActivityManagerService m = new ActivityManagerService();
1368
1369 synchronized (this) {
1370 mService = m;
1371 notifyAll();
1372 }
1373
1374 synchronized (this) {
1375 while (!mReady) {
1376 try {
1377 wait();
1378 } catch (InterruptedException e) {
1379 }
1380 }
1381 }
1382
Brad Fitzpatrickec062f62010-11-03 09:56:54 -07001383 // For debug builds, log event loop stalls to dropbox for analysis.
1384 if (StrictMode.conditionallyEnableDebugLogging()) {
1385 Slog.i(TAG, "Enabled StrictMode logging for AThread's Looper");
1386 }
1387
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001388 Looper.loop();
1389 }
1390 }
1391
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001392 static class MemBinder extends Binder {
1393 ActivityManagerService mActivityManagerService;
1394 MemBinder(ActivityManagerService activityManagerService) {
1395 mActivityManagerService = activityManagerService;
1396 }
1397
1398 @Override
1399 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1400 ActivityManagerService service = mActivityManagerService;
1401 ArrayList<ProcessRecord> procs;
1402 synchronized (mActivityManagerService) {
1403 if (args != null && args.length > 0
1404 && args[0].charAt(0) != '-') {
1405 procs = new ArrayList<ProcessRecord>();
1406 int pid = -1;
1407 try {
1408 pid = Integer.parseInt(args[0]);
1409 } catch (NumberFormatException e) {
1410
1411 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001412 for (int i=service.mLruProcesses.size()-1; i>=0; i--) {
1413 ProcessRecord proc = service.mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001414 if (proc.pid == pid) {
1415 procs.add(proc);
1416 } else if (proc.processName.equals(args[0])) {
1417 procs.add(proc);
1418 }
1419 }
1420 if (procs.size() <= 0) {
1421 pw.println("No process found for: " + args[0]);
1422 return;
1423 }
1424 } else {
Dianne Hackborn472ad872010-04-07 17:31:48 -07001425 procs = new ArrayList<ProcessRecord>(service.mLruProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001426 }
1427 }
1428 dumpApplicationMemoryUsage(fd, pw, procs, " ", args);
1429 }
1430 }
1431
1432 static class CpuBinder extends Binder {
1433 ActivityManagerService mActivityManagerService;
1434 CpuBinder(ActivityManagerService activityManagerService) {
1435 mActivityManagerService = activityManagerService;
1436 }
1437
1438 @Override
1439 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1440 synchronized (mActivityManagerService.mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07001441 pw.print(mActivityManagerService.mProcessStats.printCurrentLoad());
1442 pw.print(mActivityManagerService.mProcessStats.printCurrentState(
1443 SystemClock.uptimeMillis()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001444 }
1445 }
1446 }
1447
1448 private ActivityManagerService() {
1449 String v = System.getenv("ANDROID_SIMPLE_PROCESS_MANAGEMENT");
1450 if (v != null && Integer.getInteger(v) != 0) {
1451 mSimpleProcessManagement = true;
1452 }
1453 v = System.getenv("ANDROID_DEBUG_APP");
1454 if (v != null) {
1455 mSimpleProcessManagement = true;
1456 }
1457
Joe Onorato8a9b2202010-02-26 18:56:32 -08001458 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001459
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001460 File dataDir = Environment.getDataDirectory();
1461 File systemDir = new File(dataDir, "system");
1462 systemDir.mkdirs();
1463 mBatteryStatsService = new BatteryStatsService(new File(
1464 systemDir, "batterystats.bin").toString());
1465 mBatteryStatsService.getActiveStatistics().readLocked();
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001466 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
Dianne Hackborn287952c2010-09-22 22:34:31 -07001467 mOnBattery = DEBUG_POWER ? true
1468 : mBatteryStatsService.getActiveStatistics().getIsOnBattery();
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001469 mBatteryStatsService.getActiveStatistics().setCallback(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001470
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001471 mUsageStatsService = new UsageStatsService(new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001472 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001473
Jack Palevichb90d28c2009-07-22 15:35:24 -07001474 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1475 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1476
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001477 mConfiguration.setToDefaults();
1478 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001479 mProcessStats.init();
1480
1481 // Add ourself to the Watchdog monitors.
1482 Watchdog.getInstance().addMonitor(this);
1483
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001484 mProcessStatsThread = new Thread("ProcessStats") {
1485 public void run() {
1486 while (true) {
1487 try {
1488 try {
1489 synchronized(this) {
1490 final long now = SystemClock.uptimeMillis();
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001491 long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001492 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001493 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001494 // + ", write delay=" + nextWriteDelay);
1495 if (nextWriteDelay < nextCpuDelay) {
1496 nextCpuDelay = nextWriteDelay;
1497 }
1498 if (nextCpuDelay > 0) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001499 mProcessStatsMutexFree.set(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001500 this.wait(nextCpuDelay);
1501 }
1502 }
1503 } catch (InterruptedException e) {
1504 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001505 updateCpuStatsNow();
1506 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001507 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001508 }
1509 }
1510 }
1511 };
1512 mProcessStatsThread.start();
1513 }
1514
1515 @Override
1516 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1517 throws RemoteException {
1518 try {
1519 return super.onTransact(code, data, reply, flags);
1520 } catch (RuntimeException e) {
1521 // The activity manager only throws security exceptions, so let's
1522 // log all others.
1523 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001524 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001525 }
1526 throw e;
1527 }
1528 }
1529
1530 void updateCpuStats() {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001531 final long now = SystemClock.uptimeMillis();
1532 if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
1533 return;
1534 }
1535 if (mProcessStatsMutexFree.compareAndSet(true, false)) {
1536 synchronized (mProcessStatsThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001537 mProcessStatsThread.notify();
1538 }
1539 }
1540 }
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001541
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001542 void updateCpuStatsNow() {
1543 synchronized (mProcessStatsThread) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001544 mProcessStatsMutexFree.set(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001545 final long now = SystemClock.uptimeMillis();
1546 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001547
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001548 if (MONITOR_CPU_USAGE &&
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001549 mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
1550 mLastCpuTime.set(now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001551 haveNewCpuStats = true;
1552 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001553 //Slog.i(TAG, mProcessStats.printCurrentState());
1554 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001555 // + mProcessStats.getTotalCpuPercent() + "%");
1556
Joe Onorato8a9b2202010-02-26 18:56:32 -08001557 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001558 if ("true".equals(SystemProperties.get("events.cpu"))) {
1559 int user = mProcessStats.getLastUserTime();
1560 int system = mProcessStats.getLastSystemTime();
1561 int iowait = mProcessStats.getLastIoWaitTime();
1562 int irq = mProcessStats.getLastIrqTime();
1563 int softIrq = mProcessStats.getLastSoftIrqTime();
1564 int idle = mProcessStats.getLastIdleTime();
1565
1566 int total = user + system + iowait + irq + softIrq + idle;
1567 if (total == 0) total = 1;
1568
Doug Zongker2bec3d42009-12-04 12:52:44 -08001569 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001570 ((user+system+iowait+irq+softIrq) * 100) / total,
1571 (user * 100) / total,
1572 (system * 100) / total,
1573 (iowait * 100) / total,
1574 (irq * 100) / total,
1575 (softIrq * 100) / total);
1576 }
1577 }
1578
Amith Yamasanie43530a2009-08-21 13:11:37 -07001579 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001580 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001581 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001582 synchronized(mPidsSelfLocked) {
1583 if (haveNewCpuStats) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001584 if (mOnBattery) {
1585 int perc = bstats.startAddingCpuLocked();
1586 int totalUTime = 0;
1587 int totalSTime = 0;
Dianne Hackborn287952c2010-09-22 22:34:31 -07001588 final int N = mProcessStats.countStats();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001589 for (int i=0; i<N; i++) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001590 ProcessStats.Stats st = mProcessStats.getStats(i);
1591 if (!st.working) {
1592 continue;
1593 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001594 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001595 int otherUTime = (st.rel_utime*perc)/100;
1596 int otherSTime = (st.rel_stime*perc)/100;
1597 totalUTime += otherUTime;
1598 totalSTime += otherSTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001599 if (pr != null) {
1600 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001601 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1602 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001603 ps.addSpeedStepTimes(cpuSpeedTimes);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001604 pr.curCpuTime += (st.rel_utime+st.rel_stime) * 10;
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001605 } else {
1606 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001607 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001608 if (ps != null) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001609 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1610 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001611 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001612 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001613 }
1614 }
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001615 bstats.finishAddingCpuLocked(perc, totalUTime,
1616 totalSTime, cpuSpeedTimes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001617 }
1618 }
1619 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001620
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001621 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1622 mLastWriteTime = now;
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001623 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001624 }
1625 }
1626 }
1627 }
1628
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001629 @Override
1630 public void batteryNeedsCpuUpdate() {
1631 updateCpuStatsNow();
1632 }
1633
1634 @Override
1635 public void batteryPowerChanged(boolean onBattery) {
1636 // When plugging in, update the CPU stats first before changing
1637 // the plug state.
1638 updateCpuStatsNow();
1639 synchronized (this) {
1640 synchronized(mPidsSelfLocked) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001641 mOnBattery = DEBUG_POWER ? true : onBattery;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001642 }
1643 }
1644 }
1645
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001646 /**
1647 * Initialize the application bind args. These are passed to each
1648 * process when the bindApplication() IPC is sent to the process. They're
1649 * lazily setup to make sure the services are running when they're asked for.
1650 */
1651 private HashMap<String, IBinder> getCommonServicesLocked() {
1652 if (mAppBindArgs == null) {
1653 mAppBindArgs = new HashMap<String, IBinder>();
1654
1655 // Setup the application init args
1656 mAppBindArgs.put("package", ServiceManager.getService("package"));
1657 mAppBindArgs.put("window", ServiceManager.getService("window"));
1658 mAppBindArgs.put(Context.ALARM_SERVICE,
1659 ServiceManager.getService(Context.ALARM_SERVICE));
1660 }
1661 return mAppBindArgs;
1662 }
1663
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001664 final void setFocusedActivityLocked(ActivityRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001665 if (mFocusedActivity != r) {
1666 mFocusedActivity = r;
1667 mWindowManager.setFocusedApp(r, true);
1668 }
1669 }
1670
Dianne Hackborn906497c2010-05-10 15:57:38 -07001671 private final void updateLruProcessInternalLocked(ProcessRecord app,
1672 boolean oomAdj, boolean updateActivityTime, int bestPos) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001673 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001674 int lrui = mLruProcesses.indexOf(app);
1675 if (lrui >= 0) mLruProcesses.remove(lrui);
1676
1677 int i = mLruProcesses.size()-1;
1678 int skipTop = 0;
1679
Dianne Hackborn906497c2010-05-10 15:57:38 -07001680 app.lruSeq = mLruSeq;
1681
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001682 // compute the new weight for this process.
1683 if (updateActivityTime) {
1684 app.lastActivityTime = SystemClock.uptimeMillis();
1685 }
1686 if (app.activities.size() > 0) {
1687 // If this process has activities, we more strongly want to keep
1688 // it around.
1689 app.lruWeight = app.lastActivityTime;
1690 } else if (app.pubProviders.size() > 0) {
1691 // If this process contains content providers, we want to keep
1692 // it a little more strongly.
1693 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1694 // Also don't let it kick out the first few "real" hidden processes.
1695 skipTop = MIN_HIDDEN_APPS;
1696 } else {
1697 // If this process doesn't have activities, we less strongly
1698 // want to keep it around, and generally want to avoid getting
1699 // in front of any very recently used activities.
1700 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1701 // Also don't let it kick out the first few "real" hidden processes.
1702 skipTop = MIN_HIDDEN_APPS;
1703 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001704
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001705 while (i >= 0) {
1706 ProcessRecord p = mLruProcesses.get(i);
1707 // If this app shouldn't be in front of the first N background
1708 // apps, then skip over that many that are currently hidden.
1709 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1710 skipTop--;
1711 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001712 if (p.lruWeight <= app.lruWeight || i < bestPos) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001713 mLruProcesses.add(i+1, app);
1714 break;
1715 }
1716 i--;
1717 }
1718 if (i < 0) {
1719 mLruProcesses.add(0, app);
1720 }
1721
Dianne Hackborn906497c2010-05-10 15:57:38 -07001722 // If the app is currently using a content provider or service,
1723 // bump those processes as well.
1724 if (app.connections.size() > 0) {
1725 for (ConnectionRecord cr : app.connections) {
1726 if (cr.binding != null && cr.binding.service != null
1727 && cr.binding.service.app != null
1728 && cr.binding.service.app.lruSeq != mLruSeq) {
1729 updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,
1730 updateActivityTime, i+1);
1731 }
1732 }
1733 }
1734 if (app.conProviders.size() > 0) {
1735 for (ContentProviderRecord cpr : app.conProviders.keySet()) {
1736 if (cpr.app != null && cpr.app.lruSeq != mLruSeq) {
1737 updateLruProcessInternalLocked(cpr.app, oomAdj,
1738 updateActivityTime, i+1);
1739 }
1740 }
1741 }
1742
Joe Onorato8a9b2202010-02-26 18:56:32 -08001743 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001744 if (oomAdj) {
1745 updateOomAdjLocked();
1746 }
1747 }
1748
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001749 final void updateLruProcessLocked(ProcessRecord app,
Dianne Hackborn906497c2010-05-10 15:57:38 -07001750 boolean oomAdj, boolean updateActivityTime) {
1751 mLruSeq++;
1752 updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
1753 }
1754
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001755 final ProcessRecord getProcessRecordLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001756 String processName, int uid) {
1757 if (uid == Process.SYSTEM_UID) {
1758 // The system gets to run in any process. If there are multiple
1759 // processes with the same uid, just pick the first (this
1760 // should never happen).
1761 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1762 processName);
1763 return procs != null ? procs.valueAt(0) : null;
1764 }
1765 ProcessRecord proc = mProcessNames.get(processName, uid);
1766 return proc;
1767 }
1768
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001769 void ensurePackageDexOpt(String packageName) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001770 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001771 try {
1772 if (pm.performDexOpt(packageName)) {
1773 mDidDexOpt = true;
1774 }
1775 } catch (RemoteException e) {
1776 }
1777 }
1778
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001779 boolean isNextTransitionForward() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001780 int transit = mWindowManager.getPendingAppTransition();
1781 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1782 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1783 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1784 }
1785
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001786 final ProcessRecord startProcessLocked(String processName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001787 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001788 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001789 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1790 // We don't have to do anything more if:
1791 // (1) There is an existing application record; and
1792 // (2) The caller doesn't think it is dead, OR there is no thread
1793 // object attached to it so we know it couldn't have crashed; and
1794 // (3) There is a pid assigned to it, so it is either starting or
1795 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001796 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001797 + " app=" + app + " knownToBeDead=" + knownToBeDead
1798 + " thread=" + (app != null ? app.thread : null)
1799 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01001800 if (app != null && app.pid > 0) {
1801 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001802 // We already have the app running, or are waiting for it to
1803 // come up (we have a pid but not yet its thread), so keep it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001804 if (DEBUG_PROCESSES) Slog.v(TAG, "App already running: " + app);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001805 return app;
1806 } else {
1807 // An application record is attached to a previous process,
1808 // clean it up now.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001809 if (DEBUG_PROCESSES) Slog.v(TAG, "App died: " + app);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001810 handleAppDiedLocked(app, true);
1811 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001812 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01001813
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001814 String hostingNameStr = hostingName != null
1815 ? hostingName.flattenToShortString() : null;
1816
1817 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1818 // If we are in the background, then check to see if this process
1819 // is bad. If so, we will just silently fail.
1820 if (mBadProcesses.get(info.processName, info.uid) != null) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001821 if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid
1822 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001823 return null;
1824 }
1825 } else {
1826 // When the user is explicitly starting a process, then clear its
1827 // crash count so that we won't make it bad until they see at
1828 // least one crash dialog again, and make the process good again
1829 // if it had been bad.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001830 if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
1831 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001832 mProcessCrashTimes.remove(info.processName, info.uid);
1833 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001834 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001835 info.processName);
1836 mBadProcesses.remove(info.processName, info.uid);
1837 if (app != null) {
1838 app.bad = false;
1839 }
1840 }
1841 }
1842
1843 if (app == null) {
1844 app = newProcessRecordLocked(null, info, processName);
1845 mProcessNames.put(processName, info.uid, app);
1846 } else {
1847 // If this is a new package in the process, add the package to the list
1848 app.addPackage(info.packageName);
1849 }
1850
1851 // If the system is not ready yet, then hold off on starting this
1852 // process until it is.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001853 if (!mProcessesReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001854 && !isAllowedWhileBooting(info)
1855 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001856 if (!mProcessesOnHold.contains(app)) {
1857 mProcessesOnHold.add(app);
1858 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001859 if (DEBUG_PROCESSES) Slog.v(TAG, "System not ready, putting on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001860 return app;
1861 }
1862
1863 startProcessLocked(app, hostingType, hostingNameStr);
1864 return (app.pid != 0) ? app : null;
1865 }
1866
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001867 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1868 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1869 }
1870
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001871 private final void startProcessLocked(ProcessRecord app,
1872 String hostingType, String hostingNameStr) {
1873 if (app.pid > 0 && app.pid != MY_PID) {
1874 synchronized (mPidsSelfLocked) {
1875 mPidsSelfLocked.remove(app.pid);
1876 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1877 }
1878 app.pid = 0;
1879 }
1880
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001881 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
1882 "startProcessLocked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001883 mProcessesOnHold.remove(app);
1884
1885 updateCpuStats();
1886
1887 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1888 mProcDeaths[0] = 0;
1889
1890 try {
1891 int uid = app.info.uid;
1892 int[] gids = null;
1893 try {
1894 gids = mContext.getPackageManager().getPackageGids(
1895 app.info.packageName);
1896 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001897 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001898 }
1899 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1900 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1901 && mTopComponent != null
1902 && app.processName.equals(mTopComponent.getPackageName())) {
1903 uid = 0;
1904 }
1905 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1906 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1907 uid = 0;
1908 }
1909 }
1910 int debugFlags = 0;
1911 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1912 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
1913 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08001914 // Run the app in safe mode if its manifest requests so or the
1915 // system is booted in safe mode.
1916 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
1917 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08001918 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1919 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001920 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1921 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1922 }
1923 if ("1".equals(SystemProperties.get("debug.assert"))) {
1924 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1925 }
1926 int pid = Process.start("android.app.ActivityThread",
1927 mSimpleProcessManagement ? app.processName : null, uid, uid,
1928 gids, debugFlags, null);
1929 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
1930 synchronized (bs) {
1931 if (bs.isOnBattery()) {
1932 app.batteryStats.incStartsLocked();
1933 }
1934 }
1935
Doug Zongker2bec3d42009-12-04 12:52:44 -08001936 EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001937 app.processName, hostingType,
1938 hostingNameStr != null ? hostingNameStr : "");
1939
1940 if (app.persistent) {
Christopher Tatec27181c2010-06-30 14:41:09 -07001941 Watchdog.getInstance().processStarted(app.processName, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001942 }
1943
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001944 StringBuilder buf = mStringBuilder;
1945 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001946 buf.append("Start proc ");
1947 buf.append(app.processName);
1948 buf.append(" for ");
1949 buf.append(hostingType);
1950 if (hostingNameStr != null) {
1951 buf.append(" ");
1952 buf.append(hostingNameStr);
1953 }
1954 buf.append(": pid=");
1955 buf.append(pid);
1956 buf.append(" uid=");
1957 buf.append(uid);
1958 buf.append(" gids={");
1959 if (gids != null) {
1960 for (int gi=0; gi<gids.length; gi++) {
1961 if (gi != 0) buf.append(", ");
1962 buf.append(gids[gi]);
1963
1964 }
1965 }
1966 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08001967 Slog.i(TAG, buf.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001968 if (pid == 0 || pid == MY_PID) {
1969 // Processes are being emulated with threads.
1970 app.pid = MY_PID;
1971 app.removed = false;
1972 mStartingProcesses.add(app);
1973 } else if (pid > 0) {
1974 app.pid = pid;
1975 app.removed = false;
1976 synchronized (mPidsSelfLocked) {
1977 this.mPidsSelfLocked.put(pid, app);
1978 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1979 msg.obj = app;
1980 mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
1981 }
1982 } else {
1983 app.pid = 0;
1984 RuntimeException e = new RuntimeException(
1985 "Failure starting process " + app.processName
1986 + ": returned pid=" + pid);
Joe Onorato8a9b2202010-02-26 18:56:32 -08001987 Slog.e(TAG, e.getMessage(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001988 }
1989 } catch (RuntimeException e) {
1990 // XXX do better error recovery.
1991 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001992 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001993 }
1994 }
1995
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001996 void updateUsageStats(ActivityRecord resumedComponent, boolean resumed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001997 if (resumed) {
1998 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
1999 } else {
2000 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
2001 }
2002 }
2003
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002004 boolean startHomeActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002005 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
2006 && mTopAction == null) {
2007 // We are running in factory test mode, but unable to find
2008 // the factory test app, so just sit around displaying the
2009 // error message and don't try to start anything.
2010 return false;
2011 }
2012 Intent intent = new Intent(
2013 mTopAction,
2014 mTopData != null ? Uri.parse(mTopData) : null);
2015 intent.setComponent(mTopComponent);
2016 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
2017 intent.addCategory(Intent.CATEGORY_HOME);
2018 }
2019 ActivityInfo aInfo =
2020 intent.resolveActivityInfo(mContext.getPackageManager(),
2021 STOCK_PM_FLAGS);
2022 if (aInfo != null) {
2023 intent.setComponent(new ComponentName(
2024 aInfo.applicationInfo.packageName, aInfo.name));
2025 // Don't do this if the home app is currently being
2026 // instrumented.
2027 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
2028 aInfo.applicationInfo.uid);
2029 if (app == null || app.instrumentationClass == null) {
2030 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002031 mMainStack.startActivityLocked(null, intent, null, null, 0, aInfo,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002032 null, null, 0, 0, 0, false, false, null);
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002033 }
2034 }
2035
2036
2037 return true;
2038 }
2039
2040 /**
2041 * Starts the "new version setup screen" if appropriate.
2042 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002043 void startSetupActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002044 // Only do this once per boot.
2045 if (mCheckedForSetup) {
2046 return;
2047 }
2048
2049 // We will show this screen if the current one is a different
2050 // version than the last one shown, and we are not running in
2051 // low-level factory test mode.
2052 final ContentResolver resolver = mContext.getContentResolver();
2053 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
2054 Settings.Secure.getInt(resolver,
2055 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
2056 mCheckedForSetup = true;
2057
2058 // See if we should be showing the platform update setup UI.
2059 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
2060 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
2061 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
2062
2063 // We don't allow third party apps to replace this.
2064 ResolveInfo ri = null;
2065 for (int i=0; ris != null && i<ris.size(); i++) {
2066 if ((ris.get(i).activityInfo.applicationInfo.flags
2067 & ApplicationInfo.FLAG_SYSTEM) != 0) {
2068 ri = ris.get(i);
2069 break;
2070 }
2071 }
2072
2073 if (ri != null) {
2074 String vers = ri.activityInfo.metaData != null
2075 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
2076 : null;
2077 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
2078 vers = ri.activityInfo.applicationInfo.metaData.getString(
2079 Intent.METADATA_SETUP_VERSION);
2080 }
2081 String lastVers = Settings.Secure.getString(
2082 resolver, Settings.Secure.LAST_SETUP_SHOWN);
2083 if (vers != null && !vers.equals(lastVers)) {
2084 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2085 intent.setComponent(new ComponentName(
2086 ri.activityInfo.packageName, ri.activityInfo.name));
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002087 mMainStack.startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002088 null, null, 0, 0, 0, false, false, null);
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002089 }
2090 }
2091 }
2092 }
2093
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002094 void reportResumedActivityLocked(ActivityRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002095 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002096
2097 final int identHash = System.identityHashCode(r);
2098 updateUsageStats(r, true);
2099
2100 int i = mWatchers.beginBroadcast();
2101 while (i > 0) {
2102 i--;
2103 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2104 if (w != null) {
2105 try {
2106 w.activityResuming(identHash);
2107 } catch (RemoteException e) {
2108 }
2109 }
2110 }
2111 mWatchers.finishBroadcast();
2112 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002113
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002114 final void doPendingActivityLaunchesLocked(boolean doResume) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002115 final int N = mPendingActivityLaunches.size();
2116 if (N <= 0) {
2117 return;
2118 }
2119 for (int i=0; i<N; i++) {
2120 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002121 mMainStack.startActivityUncheckedLocked(pal.r, pal.sourceRecord,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002122 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
2123 doResume && i == (N-1));
2124 }
2125 mPendingActivityLaunches.clear();
2126 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002127
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002128 public final int startActivity(IApplicationThread caller,
2129 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2130 int grantedMode, IBinder resultTo,
2131 String resultWho, int requestCode, boolean onlyIfNeeded,
2132 boolean debug) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002133 return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002134 grantedUriPermissions, grantedMode, resultTo, resultWho,
2135 requestCode, onlyIfNeeded, debug, null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002136 }
2137
2138 public final WaitResult startActivityAndWait(IApplicationThread caller,
2139 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2140 int grantedMode, IBinder resultTo,
2141 String resultWho, int requestCode, boolean onlyIfNeeded,
2142 boolean debug) {
2143 WaitResult res = new WaitResult();
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002144 mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002145 grantedUriPermissions, grantedMode, resultTo, resultWho,
2146 requestCode, onlyIfNeeded, debug, res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002147 return res;
2148 }
2149
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002150 public final int startActivityWithConfig(IApplicationThread caller,
2151 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2152 int grantedMode, IBinder resultTo,
2153 String resultWho, int requestCode, boolean onlyIfNeeded,
2154 boolean debug, Configuration config) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002155 return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002156 grantedUriPermissions, grantedMode, resultTo, resultWho,
2157 requestCode, onlyIfNeeded, debug, null, config);
2158 }
2159
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002160 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002161 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002162 IBinder resultTo, String resultWho, int requestCode,
2163 int flagsMask, int flagsValues) {
2164 // Refuse possible leaked file descriptors
2165 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
2166 throw new IllegalArgumentException("File descriptors passed in Intent");
2167 }
2168
2169 IIntentSender sender = intent.getTarget();
2170 if (!(sender instanceof PendingIntentRecord)) {
2171 throw new IllegalArgumentException("Bad PendingIntent object");
2172 }
2173
2174 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002175
2176 synchronized (this) {
2177 // If this is coming from the currently resumed activity, it is
2178 // effectively saying that app switches are allowed at this point.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002179 if (mMainStack.mResumedActivity != null
2180 && mMainStack.mResumedActivity.info.applicationInfo.uid ==
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002181 Binder.getCallingUid()) {
2182 mAppSwitchesAllowedTime = 0;
2183 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002184 }
2185
2186 return pir.sendInner(0, fillInIntent, resolvedType,
2187 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
2188 }
2189
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002190 public boolean startNextMatchingActivity(IBinder callingActivity,
2191 Intent intent) {
2192 // Refuse possible leaked file descriptors
2193 if (intent != null && intent.hasFileDescriptors() == true) {
2194 throw new IllegalArgumentException("File descriptors passed in Intent");
2195 }
2196
2197 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002198 int index = mMainStack.indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002199 if (index < 0) {
2200 return false;
2201 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002202 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002203 if (r.app == null || r.app.thread == null) {
2204 // The caller is not running... d'oh!
2205 return false;
2206 }
2207 intent = new Intent(intent);
2208 // The caller is not allowed to change the data.
2209 intent.setDataAndType(r.intent.getData(), r.intent.getType());
2210 // And we are resetting to find the next component...
2211 intent.setComponent(null);
2212
2213 ActivityInfo aInfo = null;
2214 try {
2215 List<ResolveInfo> resolves =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002216 AppGlobals.getPackageManager().queryIntentActivities(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002217 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002218 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002219
2220 // Look for the original activity in the list...
2221 final int N = resolves != null ? resolves.size() : 0;
2222 for (int i=0; i<N; i++) {
2223 ResolveInfo rInfo = resolves.get(i);
2224 if (rInfo.activityInfo.packageName.equals(r.packageName)
2225 && rInfo.activityInfo.name.equals(r.info.name)) {
2226 // We found the current one... the next matching is
2227 // after it.
2228 i++;
2229 if (i<N) {
2230 aInfo = resolves.get(i).activityInfo;
2231 }
2232 break;
2233 }
2234 }
2235 } catch (RemoteException e) {
2236 }
2237
2238 if (aInfo == null) {
2239 // Nobody who is next!
2240 return false;
2241 }
2242
2243 intent.setComponent(new ComponentName(
2244 aInfo.applicationInfo.packageName, aInfo.name));
2245 intent.setFlags(intent.getFlags()&~(
2246 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
2247 Intent.FLAG_ACTIVITY_CLEAR_TOP|
2248 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
2249 Intent.FLAG_ACTIVITY_NEW_TASK));
2250
2251 // Okay now we need to start the new activity, replacing the
2252 // currently running activity. This is a little tricky because
2253 // we want to start the new one as if the current one is finished,
2254 // but not finish the current one first so that there is no flicker.
2255 // And thus...
2256 final boolean wasFinishing = r.finishing;
2257 r.finishing = true;
2258
2259 // Propagate reply information over to the new activity.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002260 final ActivityRecord resultTo = r.resultTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002261 final String resultWho = r.resultWho;
2262 final int requestCode = r.requestCode;
2263 r.resultTo = null;
2264 if (resultTo != null) {
2265 resultTo.removeResultsLocked(r, resultWho, requestCode);
2266 }
2267
2268 final long origId = Binder.clearCallingIdentity();
2269 // XXX we are not dealing with propagating grantedUriPermissions...
2270 // those are not yet exposed to user code, so there is no need.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002271 int res = mMainStack.startActivityLocked(r.app.thread, intent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002272 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002273 requestCode, -1, r.launchedFromUid, false, false, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002274 Binder.restoreCallingIdentity(origId);
2275
2276 r.finishing = wasFinishing;
2277 if (res != START_SUCCESS) {
2278 return false;
2279 }
2280 return true;
2281 }
2282 }
2283
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002284 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002285 Intent intent, String resolvedType, IBinder resultTo,
2286 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002287
2288 // This is so super not safe, that only the system (or okay root)
2289 // can do it.
2290 final int callingUid = Binder.getCallingUid();
2291 if (callingUid != 0 && callingUid != Process.myUid()) {
2292 throw new SecurityException(
2293 "startActivityInPackage only available to the system");
2294 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002295
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002296 return mMainStack.startActivityMayWait(null, uid, intent, resolvedType,
2297 null, 0, resultTo, resultWho, requestCode, onlyIfNeeded, false, null, null);
2298 }
2299
2300 public final int startActivities(IApplicationThread caller,
2301 Intent[] intents, String[] resolvedTypes, IBinder resultTo) {
2302 return mMainStack.startActivities(caller, -1, intents, resolvedTypes, resultTo);
2303 }
2304
2305 public final int startActivitiesInPackage(int uid,
2306 Intent[] intents, String[] resolvedTypes, IBinder resultTo) {
2307
2308 // This is so super not safe, that only the system (or okay root)
2309 // can do it.
2310 final int callingUid = Binder.getCallingUid();
2311 if (callingUid != 0 && callingUid != Process.myUid()) {
2312 throw new SecurityException(
2313 "startActivityInPackage only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002314 }
2315
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002316 return mMainStack.startActivities(null, uid, intents, resolvedTypes, resultTo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002317 }
2318
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002319 final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002320 int N = mRecentTasks.size();
Dianne Hackborn7c0e75e2010-12-21 19:15:40 -08002321 // Quick case: check if the top-most recent task is the same.
2322 if (N > 0 && mRecentTasks.get(0) == task) {
2323 return;
2324 }
2325 // Remove any existing entries that are the same kind of task.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002326 for (int i=0; i<N; i++) {
2327 TaskRecord tr = mRecentTasks.get(i);
2328 if ((task.affinity != null && task.affinity.equals(tr.affinity))
2329 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
2330 mRecentTasks.remove(i);
2331 i--;
2332 N--;
2333 if (task.intent == null) {
2334 // If the new recent task we are adding is not fully
2335 // specified, then replace it with the existing recent task.
2336 task = tr;
2337 }
2338 }
2339 }
2340 if (N >= MAX_RECENT_TASKS) {
2341 mRecentTasks.remove(N-1);
2342 }
2343 mRecentTasks.add(0, task);
2344 }
2345
2346 public void setRequestedOrientation(IBinder token,
2347 int requestedOrientation) {
2348 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002349 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002350 if (index < 0) {
2351 return;
2352 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002353 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002354 final long origId = Binder.clearCallingIdentity();
2355 mWindowManager.setAppOrientation(r, requestedOrientation);
2356 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07002357 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002358 r.mayFreezeScreenLocked(r.app) ? r : null);
2359 if (config != null) {
2360 r.frozenBeforeDestroy = true;
2361 if (!updateConfigurationLocked(config, r)) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002362 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002363 }
2364 }
2365 Binder.restoreCallingIdentity(origId);
2366 }
2367 }
2368
2369 public int getRequestedOrientation(IBinder token) {
2370 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002371 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002372 if (index < 0) {
2373 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
2374 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002375 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002376 return mWindowManager.getAppOrientation(r);
2377 }
2378 }
2379
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002380 /**
2381 * This is the internal entry point for handling Activity.finish().
2382 *
2383 * @param token The Binder token referencing the Activity we want to finish.
2384 * @param resultCode Result code, if any, from this Activity.
2385 * @param resultData Result data (Intent), if any, from this Activity.
2386 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11002387 * @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 -08002388 */
2389 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
2390 // Refuse possible leaked file descriptors
2391 if (resultData != null && resultData.hasFileDescriptors() == true) {
2392 throw new IllegalArgumentException("File descriptors passed in Intent");
2393 }
2394
2395 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002396 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002397 // Find the first activity that is not finishing.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002398 ActivityRecord next = mMainStack.topRunningActivityLocked(token, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002399 if (next != null) {
2400 // ask watcher if this is allowed
2401 boolean resumeOK = true;
2402 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002403 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002404 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002405 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002406 }
2407
2408 if (!resumeOK) {
2409 return false;
2410 }
2411 }
2412 }
2413 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002414 boolean res = mMainStack.requestFinishActivityLocked(token, resultCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002415 resultData, "app-request");
2416 Binder.restoreCallingIdentity(origId);
2417 return res;
2418 }
2419 }
2420
Dianne Hackborn860755f2010-06-03 18:47:52 -07002421 public final void finishHeavyWeightApp() {
2422 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2423 != PackageManager.PERMISSION_GRANTED) {
2424 String msg = "Permission Denial: finishHeavyWeightApp() from pid="
2425 + Binder.getCallingPid()
2426 + ", uid=" + Binder.getCallingUid()
2427 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2428 Slog.w(TAG, msg);
2429 throw new SecurityException(msg);
2430 }
2431
2432 synchronized(this) {
2433 if (mHeavyWeightProcess == null) {
2434 return;
2435 }
2436
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002437 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>(
Dianne Hackborn860755f2010-06-03 18:47:52 -07002438 mHeavyWeightProcess.activities);
2439 for (int i=0; i<activities.size(); i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002440 ActivityRecord r = activities.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002441 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002442 int index = mMainStack.indexOfTokenLocked(r);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002443 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002444 mMainStack.finishActivityLocked(r, index, Activity.RESULT_CANCELED,
Dianne Hackborn860755f2010-06-03 18:47:52 -07002445 null, "finish-heavy");
2446 }
2447 }
2448 }
2449
2450 mHeavyWeightProcess = null;
2451 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
2452 }
2453 }
2454
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002455 public void crashApplication(int uid, int initialPid, String packageName,
2456 String message) {
2457 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2458 != PackageManager.PERMISSION_GRANTED) {
2459 String msg = "Permission Denial: crashApplication() from pid="
2460 + Binder.getCallingPid()
2461 + ", uid=" + Binder.getCallingUid()
2462 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2463 Slog.w(TAG, msg);
2464 throw new SecurityException(msg);
2465 }
2466
2467 synchronized(this) {
2468 ProcessRecord proc = null;
2469
2470 // Figure out which process to kill. We don't trust that initialPid
2471 // still has any relation to current pids, so must scan through the
2472 // list.
2473 synchronized (mPidsSelfLocked) {
2474 for (int i=0; i<mPidsSelfLocked.size(); i++) {
2475 ProcessRecord p = mPidsSelfLocked.valueAt(i);
2476 if (p.info.uid != uid) {
2477 continue;
2478 }
2479 if (p.pid == initialPid) {
2480 proc = p;
2481 break;
2482 }
2483 for (String str : p.pkgList) {
2484 if (str.equals(packageName)) {
2485 proc = p;
2486 }
2487 }
2488 }
2489 }
2490
2491 if (proc == null) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07002492 Slog.w(TAG, "crashApplication: nothing for uid=" + uid
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002493 + " initialPid=" + initialPid
2494 + " packageName=" + packageName);
2495 return;
2496 }
2497
2498 if (proc.thread != null) {
Dianne Hackborn9f531192010-08-04 17:48:03 -07002499 if (proc.pid == Process.myPid()) {
2500 Log.w(TAG, "crashApplication: trying to crash self!");
2501 return;
2502 }
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002503 long ident = Binder.clearCallingIdentity();
2504 try {
2505 proc.thread.scheduleCrash(message);
2506 } catch (RemoteException e) {
2507 }
2508 Binder.restoreCallingIdentity(ident);
2509 }
2510 }
2511 }
2512
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002513 public final void finishSubActivity(IBinder token, String resultWho,
2514 int requestCode) {
2515 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002516 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002517 if (index < 0) {
2518 return;
2519 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002520 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002521
2522 final long origId = Binder.clearCallingIdentity();
2523
2524 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002525 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2526 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002527 if (r.resultTo == self && r.requestCode == requestCode) {
2528 if ((r.resultWho == null && resultWho == null) ||
2529 (r.resultWho != null && r.resultWho.equals(resultWho))) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002530 mMainStack.finishActivityLocked(r, i,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002531 Activity.RESULT_CANCELED, null, "request-sub");
2532 }
2533 }
2534 }
2535
2536 Binder.restoreCallingIdentity(origId);
2537 }
2538 }
2539
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002540 public boolean willActivityBeVisible(IBinder token) {
2541 synchronized(this) {
2542 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002543 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2544 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002545 if (r == token) {
2546 return true;
2547 }
2548 if (r.fullscreen && !r.finishing) {
2549 return false;
2550 }
2551 }
2552 return true;
2553 }
2554 }
2555
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002556 public void overridePendingTransition(IBinder token, String packageName,
2557 int enterAnim, int exitAnim) {
2558 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002559 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002560 if (index < 0) {
2561 return;
2562 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002563 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002564
2565 final long origId = Binder.clearCallingIdentity();
2566
2567 if (self.state == ActivityState.RESUMED
2568 || self.state == ActivityState.PAUSING) {
2569 mWindowManager.overridePendingAppTransition(packageName,
2570 enterAnim, exitAnim);
2571 }
2572
2573 Binder.restoreCallingIdentity(origId);
2574 }
2575 }
2576
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002577 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002578 * Main function for removing an existing process from the activity manager
2579 * as a result of that process going away. Clears out all connections
2580 * to the process.
2581 */
2582 private final void handleAppDiedLocked(ProcessRecord app,
2583 boolean restarting) {
2584 cleanUpApplicationRecordLocked(app, restarting, -1);
2585 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002586 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002587 }
2588
2589 // Just in case...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002590 if (mMainStack.mPausingActivity != null && mMainStack.mPausingActivity.app == app) {
2591 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " +mMainStack.mPausingActivity);
2592 mMainStack.mPausingActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002593 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002594 if (mMainStack.mLastPausedActivity != null && mMainStack.mLastPausedActivity.app == app) {
2595 mMainStack.mLastPausedActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002596 }
2597
2598 // Remove this application's activities from active lists.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002599 mMainStack.removeHistoryRecordsForAppLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002600
2601 boolean atTop = true;
2602 boolean hasVisibleActivities = false;
2603
2604 // Clean out the history list.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002605 int i = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002606 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002607 TAG, "Removing app " + app + " from history with " + i + " entries");
2608 while (i > 0) {
2609 i--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002610 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002611 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002612 TAG, "Record #" + i + " " + r + ": app=" + r.app);
2613 if (r.app == app) {
2614 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002615 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002616 TAG, "Removing this entry! frozen=" + r.haveState
2617 + " finishing=" + r.finishing);
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -08002618 r.makeFinishing();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002619 mMainStack.mHistory.remove(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002620
2621 r.inHistory = false;
2622 mWindowManager.removeAppToken(r);
2623 if (VALIDATE_TOKENS) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002624 mWindowManager.validateAppTokens(mMainStack.mHistory);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002625 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002626 r.removeUriPermissionsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002627
2628 } else {
2629 // We have the current state for this activity, so
2630 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002631 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002632 TAG, "Keeping entry, setting app to null");
2633 if (r.visible) {
2634 hasVisibleActivities = true;
2635 }
2636 r.app = null;
2637 r.nowVisible = false;
2638 if (!r.haveState) {
2639 r.icicle = null;
2640 }
2641 }
2642
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002643 r.stack.cleanUpActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002644 r.state = ActivityState.STOPPED;
2645 }
2646 atTop = false;
2647 }
2648
2649 app.activities.clear();
2650
2651 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002652 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002653 + " running instrumentation " + app.instrumentationClass);
2654 Bundle info = new Bundle();
2655 info.putString("shortMsg", "Process crashed.");
2656 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
2657 }
2658
2659 if (!restarting) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002660 if (!mMainStack.resumeTopActivityLocked(null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002661 // If there was nothing to resume, and we are not already
2662 // restarting this process, but there is a visible activity that
2663 // is hosted by the process... then make sure all visible
2664 // activities are running, taking care of restarting this
2665 // process.
2666 if (hasVisibleActivities) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002667 mMainStack.ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002668 }
2669 }
2670 }
2671 }
2672
2673 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
2674 IBinder threadBinder = thread.asBinder();
2675
2676 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002677 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2678 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002679 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
2680 return i;
2681 }
2682 }
2683 return -1;
2684 }
2685
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002686 final ProcessRecord getRecordForAppLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002687 IApplicationThread thread) {
2688 if (thread == null) {
2689 return null;
2690 }
2691
2692 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002693 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002694 }
2695
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002696 final void appDiedLocked(ProcessRecord app, int pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002697 IApplicationThread thread) {
2698
2699 mProcDeaths[0]++;
2700
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07002701 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
2702 synchronized (stats) {
2703 stats.noteProcessDiedLocked(app.info.uid, pid);
2704 }
2705
Magnus Edlund7bb25812010-02-24 15:45:06 +01002706 // Clean up already done if the process has been re-started.
2707 if (app.pid == pid && app.thread != null &&
2708 app.thread.asBinder() == thread.asBinder()) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07002709 if (!app.killedBackground) {
2710 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
2711 + ") has died.");
2712 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08002713 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002714 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002715 TAG, "Dying app: " + app + ", pid: " + pid
2716 + ", thread: " + thread.asBinder());
2717 boolean doLowMem = app.instrumentationClass == null;
2718 handleAppDiedLocked(app, false);
2719
2720 if (doLowMem) {
2721 // If there are no longer any background processes running,
2722 // and the app that died was not running instrumentation,
2723 // then tell everyone we are now low on memory.
2724 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002725 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2726 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002727 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
2728 haveBg = true;
2729 break;
2730 }
2731 }
2732
2733 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002734 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002735 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002736 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002737 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2738 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07002739 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002740 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
2741 // The low memory report is overriding any current
2742 // state for a GC request. Make sure to do
Dianne Hackborn32907cf2010-06-10 17:50:20 -07002743 // heavy/important/visible/foreground processes first.
2744 if (rec.setAdj <= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002745 rec.lastRequestedGc = 0;
2746 } else {
2747 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002748 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002749 rec.reportLowMemory = true;
2750 rec.lastLowMemory = now;
2751 mProcessesToGc.remove(rec);
2752 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002753 }
2754 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002755 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002756 }
2757 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01002758 } else if (app.pid != pid) {
2759 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002760 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01002761 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08002762 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002763 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002764 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002765 + thread.asBinder());
2766 }
2767 }
2768
Dan Egnor42471dd2010-01-07 17:25:22 -08002769 /**
2770 * If a stack trace dump file is configured, dump process stack traces.
Christopher Tate6ee412d2010-05-28 12:01:56 -07002771 * @param clearTraces causes the dump file to be erased prior to the new
2772 * traces being written, if true; when false, the new traces will be
2773 * appended to any existing file content.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002774 * @param firstPids of dalvik VM processes to dump stack traces for first
2775 * @param lastPids of dalvik VM processes to dump stack traces for last
Dan Egnor42471dd2010-01-07 17:25:22 -08002776 * @return file containing stack traces, or null if no dump file is configured
2777 */
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002778 public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> firstPids,
2779 ProcessStats processStats, SparseArray<Boolean> lastPids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002780 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
2781 if (tracesPath == null || tracesPath.length() == 0) {
2782 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002783 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002784
2785 File tracesFile = new File(tracesPath);
2786 try {
2787 File tracesDir = tracesFile.getParentFile();
2788 if (!tracesDir.exists()) tracesFile.mkdirs();
2789 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
2790
Christopher Tate6ee412d2010-05-28 12:01:56 -07002791 if (clearTraces && tracesFile.exists()) tracesFile.delete();
Dan Egnor42471dd2010-01-07 17:25:22 -08002792 tracesFile.createNewFile();
2793 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
2794 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002795 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08002796 return null;
2797 }
2798
2799 // Use a FileObserver to detect when traces finish writing.
2800 // The order of traces is considered important to maintain for legibility.
2801 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
2802 public synchronized void onEvent(int event, String path) { notify(); }
2803 };
2804
2805 try {
2806 observer.startWatching();
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002807
2808 // First collect all of the stacks of the most important pids.
2809 try {
2810 int num = firstPids.size();
2811 for (int i = 0; i < num; i++) {
2812 synchronized (observer) {
2813 Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT);
2814 observer.wait(200); // Wait for write-close, give up after 200msec
2815 }
2816 }
2817 } catch (InterruptedException e) {
2818 Log.wtf(TAG, e);
2819 }
2820
2821 // Next measure CPU usage.
2822 if (processStats != null) {
2823 processStats.init();
2824 System.gc();
2825 processStats.update();
2826 try {
2827 synchronized (processStats) {
2828 processStats.wait(500); // measure over 1/2 second.
2829 }
2830 } catch (InterruptedException e) {
2831 }
2832 processStats.update();
2833
2834 // We'll take the stack crawls of just the top apps using CPU.
2835 final int N = processStats.countWorkingStats();
2836 int numProcs = 0;
2837 for (int i=0; i<N && numProcs<5; i++) {
2838 ProcessStats.Stats stats = processStats.getWorkingStats(i);
2839 if (lastPids.indexOfKey(stats.pid) >= 0) {
2840 numProcs++;
2841 try {
2842 synchronized (observer) {
2843 Process.sendSignal(stats.pid, Process.SIGNAL_QUIT);
2844 observer.wait(200); // Wait for write-close, give up after 200msec
2845 }
2846 } catch (InterruptedException e) {
2847 Log.wtf(TAG, e);
2848 }
2849
2850 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002851 }
2852 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002853
2854 return tracesFile;
2855
Dan Egnor42471dd2010-01-07 17:25:22 -08002856 } finally {
2857 observer.stopWatching();
2858 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002859 }
2860
Jeff Brown4d94a762010-09-23 11:33:28 -07002861 private final class AppNotResponding implements Runnable {
2862 private final ProcessRecord mApp;
2863 private final String mAnnotation;
2864
2865 public AppNotResponding(ProcessRecord app, String annotation) {
2866 mApp = app;
2867 mAnnotation = annotation;
2868 }
2869
2870 @Override
2871 public void run() {
2872 appNotResponding(mApp, null, null, mAnnotation);
2873 }
2874 }
2875
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002876 final void appNotResponding(ProcessRecord app, ActivityRecord activity,
2877 ActivityRecord parent, final String annotation) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002878 ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
2879 SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20);
2880
Dianne Hackborn287952c2010-09-22 22:34:31 -07002881 if (mController != null) {
2882 try {
2883 // 0 == continue, -1 = kill process immediately
2884 int res = mController.appEarlyNotResponding(app.processName, app.pid, annotation);
2885 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2886 } catch (RemoteException e) {
2887 mController = null;
2888 }
2889 }
2890
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002891 long anrTime = SystemClock.uptimeMillis();
2892 if (MONITOR_CPU_USAGE) {
2893 updateCpuStatsNow();
2894 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002895
2896 synchronized (this) {
2897 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
2898 if (mShuttingDown) {
2899 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
2900 return;
2901 } else if (app.notResponding) {
2902 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
2903 return;
2904 } else if (app.crashing) {
2905 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
2906 return;
2907 }
2908
2909 // In case we come through here for the same app before completing
2910 // this one, mark as anring now so we will bail out.
2911 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08002912
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002913 // Log the ANR to the event log.
2914 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
2915 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08002916
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002917 // Dump thread traces as quickly as we can, starting with "interesting" processes.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002918 firstPids.add(app.pid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002919
2920 int parentPid = app.pid;
2921 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002922 if (parentPid != app.pid) firstPids.add(parentPid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002923
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002924 if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08002925
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002926 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
2927 ProcessRecord r = mLruProcesses.get(i);
2928 if (r != null && r.thread != null) {
2929 int pid = r.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002930 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
2931 if (r.persistent) {
2932 firstPids.add(pid);
2933 } else {
2934 lastPids.put(pid, Boolean.TRUE);
2935 }
2936 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002937 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002938 }
2939 }
2940
Dan Egnor42471dd2010-01-07 17:25:22 -08002941 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002942 StringBuilder info = mStringBuilder;
2943 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08002944 info.append("ANR in ").append(app.processName);
2945 if (activity != null && activity.shortComponentName != null) {
2946 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002947 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08002948 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002949 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002950 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002951 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002952 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002953 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002954 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002955
Dianne Hackborn287952c2010-09-22 22:34:31 -07002956 final ProcessStats processStats = new ProcessStats(true);
2957
2958 File tracesFile = dumpStackTraces(true, firstPids, processStats, lastPids);
2959
Dan Egnor42471dd2010-01-07 17:25:22 -08002960 String cpuInfo = null;
2961 if (MONITOR_CPU_USAGE) {
2962 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002963 synchronized (mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002964 cpuInfo = mProcessStats.printCurrentState(anrTime);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002965 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002966 info.append(processStats.printCurrentLoad());
Dan Egnor42471dd2010-01-07 17:25:22 -08002967 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002968 }
2969
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002970 info.append(processStats.printCurrentState(anrTime));
2971
Joe Onorato8a9b2202010-02-26 18:56:32 -08002972 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08002973 if (tracesFile == null) {
2974 // There is no trace file, so dump (only) the alleged culprit's threads to the log
2975 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
2976 }
2977
2978 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
2979
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002980 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002981 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08002982 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
2983 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002984 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002985 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2986 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002987 }
2988 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002989 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002990 }
2991 }
2992
Dan Egnor42471dd2010-01-07 17:25:22 -08002993 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
2994 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
2995 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002996
2997 synchronized (this) {
2998 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
2999 Process.killProcess(app.pid);
3000 return;
3001 }
3002
3003 // Set the app's notResponding state, and look up the errorReportReceiver
3004 makeAppNotRespondingLocked(app,
3005 activity != null ? activity.shortComponentName : null,
3006 annotation != null ? "ANR " + annotation : "ANR",
3007 info.toString());
3008
3009 // Bring up the infamous App Not Responding dialog
3010 Message msg = Message.obtain();
3011 HashMap map = new HashMap();
3012 msg.what = SHOW_NOT_RESPONDING_MSG;
3013 msg.obj = map;
3014 map.put("app", app);
3015 if (activity != null) {
3016 map.put("activity", activity);
3017 }
3018
3019 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08003020 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003021 }
3022
Dianne Hackborn0dad3642010-09-09 21:25:35 -07003023 final void showLaunchWarningLocked(final ActivityRecord cur, final ActivityRecord next) {
3024 if (!mLaunchWarningShown) {
3025 mLaunchWarningShown = true;
3026 mHandler.post(new Runnable() {
3027 @Override
3028 public void run() {
3029 synchronized (ActivityManagerService.this) {
3030 final Dialog d = new LaunchWarningWindow(mContext, cur, next);
3031 d.show();
3032 mHandler.postDelayed(new Runnable() {
3033 @Override
3034 public void run() {
3035 synchronized (ActivityManagerService.this) {
3036 d.dismiss();
3037 mLaunchWarningShown = false;
3038 }
3039 }
3040 }, 4000);
3041 }
3042 }
3043 });
3044 }
3045 }
3046
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003047 public boolean clearApplicationUserData(final String packageName,
3048 final IPackageDataObserver observer) {
3049 int uid = Binder.getCallingUid();
3050 int pid = Binder.getCallingPid();
3051 long callingId = Binder.clearCallingIdentity();
3052 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003053 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003054 int pkgUid = -1;
3055 synchronized(this) {
3056 try {
3057 pkgUid = pm.getPackageUid(packageName);
3058 } catch (RemoteException e) {
3059 }
3060 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003061 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003062 return false;
3063 }
3064 if (uid == pkgUid || checkComponentPermission(
3065 android.Manifest.permission.CLEAR_APP_USER_DATA,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08003066 pid, uid, -1, true)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003067 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003068 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003069 } else {
3070 throw new SecurityException(pid+" does not have permission:"+
3071 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
3072 "for process:"+packageName);
3073 }
3074 }
3075
3076 try {
3077 //clear application user data
3078 pm.clearApplicationUserData(packageName, observer);
3079 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
3080 Uri.fromParts("package", packageName, null));
3081 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003082 broadcastIntentInPackage("android", Process.SYSTEM_UID, intent,
3083 null, null, 0, null, null, null, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003084 } catch (RemoteException e) {
3085 }
3086 } finally {
3087 Binder.restoreCallingIdentity(callingId);
3088 }
3089 return true;
3090 }
3091
Dianne Hackborn03abb812010-01-04 18:43:19 -08003092 public void killBackgroundProcesses(final String packageName) {
3093 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
3094 != PackageManager.PERMISSION_GRANTED &&
3095 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
3096 != PackageManager.PERMISSION_GRANTED) {
3097 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003098 + Binder.getCallingPid()
3099 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08003100 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003101 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003102 throw new SecurityException(msg);
3103 }
3104
3105 long callingId = Binder.clearCallingIdentity();
3106 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003107 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003108 int pkgUid = -1;
3109 synchronized(this) {
3110 try {
3111 pkgUid = pm.getPackageUid(packageName);
3112 } catch (RemoteException e) {
3113 }
3114 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003115 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003116 return;
3117 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003118 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003119 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003120 }
3121 } finally {
3122 Binder.restoreCallingIdentity(callingId);
3123 }
3124 }
3125
3126 public void forceStopPackage(final String packageName) {
3127 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
3128 != PackageManager.PERMISSION_GRANTED) {
3129 String msg = "Permission Denial: forceStopPackage() from pid="
3130 + Binder.getCallingPid()
3131 + ", uid=" + Binder.getCallingUid()
3132 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003133 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003134 throw new SecurityException(msg);
3135 }
3136
3137 long callingId = Binder.clearCallingIdentity();
3138 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003139 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn03abb812010-01-04 18:43:19 -08003140 int pkgUid = -1;
3141 synchronized(this) {
3142 try {
3143 pkgUid = pm.getPackageUid(packageName);
3144 } catch (RemoteException e) {
3145 }
3146 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003147 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003148 return;
3149 }
3150 forceStopPackageLocked(packageName, pkgUid);
Dianne Hackborne7f97212011-02-24 14:40:20 -08003151 try {
3152 pm.setPackageStoppedState(packageName, true);
3153 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08003154 } catch (IllegalArgumentException e) {
3155 Slog.w(TAG, "Failed trying to unstop package "
3156 + packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08003157 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003158 }
3159 } finally {
3160 Binder.restoreCallingIdentity(callingId);
3161 }
3162 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003163
3164 /*
3165 * The pkg name and uid have to be specified.
3166 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
3167 */
3168 public void killApplicationWithUid(String pkg, int uid) {
3169 if (pkg == null) {
3170 return;
3171 }
3172 // Make sure the uid is valid.
3173 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003174 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003175 return;
3176 }
3177 int callerUid = Binder.getCallingUid();
3178 // Only the system server can kill an application
3179 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07003180 // Post an aysnc message to kill the application
3181 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
3182 msg.arg1 = uid;
3183 msg.arg2 = 0;
3184 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07003185 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003186 } else {
3187 throw new SecurityException(callerUid + " cannot kill pkg: " +
3188 pkg);
3189 }
3190 }
3191
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003192 public void closeSystemDialogs(String reason) {
3193 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003194 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003195 if (reason != null) {
3196 intent.putExtra("reason", reason);
3197 }
3198
3199 final int uid = Binder.getCallingUid();
3200 final long origId = Binder.clearCallingIdentity();
3201 synchronized (this) {
3202 int i = mWatchers.beginBroadcast();
3203 while (i > 0) {
3204 i--;
3205 IActivityWatcher w = mWatchers.getBroadcastItem(i);
3206 if (w != null) {
3207 try {
3208 w.closingSystemDialogs(reason);
3209 } catch (RemoteException e) {
3210 }
3211 }
3212 }
3213 mWatchers.finishBroadcast();
3214
Dianne Hackbornffa42482009-09-23 22:20:11 -07003215 mWindowManager.closeSystemDialogs(reason);
3216
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003217 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3218 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackbornffa42482009-09-23 22:20:11 -07003219 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003220 r.stack.finishActivityLocked(r, i,
Dianne Hackbornffa42482009-09-23 22:20:11 -07003221 Activity.RESULT_CANCELED, null, "close-sys");
3222 }
3223 }
3224
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003225 broadcastIntentLocked(null, null, intent, null,
3226 null, 0, null, null, null, false, false, -1, uid);
3227 }
3228 Binder.restoreCallingIdentity(origId);
3229 }
3230
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003231 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003232 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003233 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
3234 for (int i=pids.length-1; i>=0; i--) {
3235 infos[i] = new Debug.MemoryInfo();
3236 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003237 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003238 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003239 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07003240
3241 public void killApplicationProcess(String processName, int uid) {
3242 if (processName == null) {
3243 return;
3244 }
3245
3246 int callerUid = Binder.getCallingUid();
3247 // Only the system server can kill an application
3248 if (callerUid == Process.SYSTEM_UID) {
3249 synchronized (this) {
3250 ProcessRecord app = getProcessRecordLocked(processName, uid);
3251 if (app != null) {
3252 try {
3253 app.thread.scheduleSuicide();
3254 } catch (RemoteException e) {
3255 // If the other end already died, then our work here is done.
3256 }
3257 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003258 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07003259 + processName + " / " + uid);
3260 }
3261 }
3262 } else {
3263 throw new SecurityException(callerUid + " cannot kill app process: " +
3264 processName);
3265 }
3266 }
3267
Dianne Hackborn03abb812010-01-04 18:43:19 -08003268 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003269 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003270 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
3271 Uri.fromParts("package", packageName, null));
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003272 if (!mProcessesReady) {
3273 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
3274 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003275 intent.putExtra(Intent.EXTRA_UID, uid);
3276 broadcastIntentLocked(null, null, intent,
3277 null, null, 0, null, null, null,
3278 false, false, MY_PID, Process.SYSTEM_UID);
3279 }
3280
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003281 private final boolean killPackageProcessesLocked(String packageName, int uid,
3282 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003283 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003284
Dianne Hackborn03abb812010-01-04 18:43:19 -08003285 // Remove all processes this package may have touched: all with the
3286 // same UID (except for the system or root user), and all whose name
3287 // matches the package name.
3288 final String procNamePrefix = packageName + ":";
3289 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
3290 final int NA = apps.size();
3291 for (int ia=0; ia<NA; ia++) {
3292 ProcessRecord app = apps.valueAt(ia);
3293 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003294 if (doit) {
3295 procs.add(app);
3296 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003297 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
3298 || app.processName.equals(packageName)
3299 || app.processName.startsWith(procNamePrefix)) {
3300 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003301 if (!doit) {
3302 return true;
3303 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003304 app.removed = true;
3305 procs.add(app);
3306 }
3307 }
3308 }
3309 }
3310
3311 int N = procs.size();
3312 for (int i=0; i<N; i++) {
3313 removeProcessLocked(procs.get(i), callerWillRestart);
3314 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003315 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08003316 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003317
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003318 private final boolean forceStopPackageLocked(String name, int uid,
3319 boolean callerWillRestart, boolean purgeCache, boolean doit) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003320 int i, N;
3321
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003322 if (uid < 0) {
3323 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003324 uid = AppGlobals.getPackageManager().getPackageUid(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003325 } catch (RemoteException e) {
3326 }
3327 }
3328
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003329 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003330 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003331
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003332 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
3333 while (badApps.hasNext()) {
3334 SparseArray<Long> ba = badApps.next();
3335 if (ba.get(uid) != null) {
3336 badApps.remove();
3337 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003338 }
3339 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003340
3341 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
3342 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003343
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003344 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3345 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003346 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003347 if (!doit) {
3348 return true;
3349 }
3350 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003351 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003352 if (r.app != null) {
3353 r.app.removed = true;
3354 }
3355 r.app = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003356 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003357 }
3358 }
3359
3360 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
3361 for (ServiceRecord service : mServices.values()) {
3362 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003363 if (!doit) {
3364 return true;
3365 }
3366 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003367 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003368 if (service.app != null) {
3369 service.app.removed = true;
3370 }
3371 service.app = null;
3372 services.add(service);
3373 }
3374 }
3375
3376 N = services.size();
3377 for (i=0; i<N; i++) {
3378 bringDownServiceLocked(services.get(i), true);
3379 }
3380
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003381 if (doit) {
3382 if (purgeCache) {
3383 AttributeCache ac = AttributeCache.instance();
3384 if (ac != null) {
3385 ac.removePackage(name);
3386 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003387 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003388 mMainStack.resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003389 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003390
3391 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003392 }
3393
3394 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
3395 final String name = app.processName;
3396 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003397 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003398 TAG, "Force removing process " + app + " (" + name
3399 + "/" + uid + ")");
3400
3401 mProcessNames.remove(name, uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003402 if (mHeavyWeightProcess == app) {
3403 mHeavyWeightProcess = null;
3404 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3405 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003406 boolean needRestart = false;
3407 if (app.pid > 0 && app.pid != MY_PID) {
3408 int pid = app.pid;
3409 synchronized (mPidsSelfLocked) {
3410 mPidsSelfLocked.remove(pid);
3411 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3412 }
3413 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003414 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003415 Process.killProcess(pid);
3416
3417 if (app.persistent) {
3418 if (!callerWillRestart) {
3419 addAppLocked(app.info);
3420 } else {
3421 needRestart = true;
3422 }
3423 }
3424 } else {
3425 mRemovedProcesses.add(app);
3426 }
3427
3428 return needRestart;
3429 }
3430
3431 private final void processStartTimedOutLocked(ProcessRecord app) {
3432 final int pid = app.pid;
3433 boolean gone = false;
3434 synchronized (mPidsSelfLocked) {
3435 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
3436 if (knownApp != null && knownApp.thread == null) {
3437 mPidsSelfLocked.remove(pid);
3438 gone = true;
3439 }
3440 }
3441
3442 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003443 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003444 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003445 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003446 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003447 if (mHeavyWeightProcess == app) {
3448 mHeavyWeightProcess = null;
3449 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3450 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003451 // Take care of any launching providers waiting for this process.
3452 checkAppInLaunchingProvidersLocked(app, true);
3453 // Take care of any services that are waiting for the process.
3454 for (int i=0; i<mPendingServices.size(); i++) {
3455 ServiceRecord sr = mPendingServices.get(i);
3456 if (app.info.uid == sr.appInfo.uid
3457 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003458 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003459 mPendingServices.remove(i);
3460 i--;
3461 bringDownServiceLocked(sr, true);
3462 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003463 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003464 Process.killProcess(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07003465 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003466 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07003467 try {
3468 IBackupManager bm = IBackupManager.Stub.asInterface(
3469 ServiceManager.getService(Context.BACKUP_SERVICE));
3470 bm.agentDisconnected(app.info.packageName);
3471 } catch (RemoteException e) {
3472 // Can't happen; the backup manager is local
3473 }
3474 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003475 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003476 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003477 mPendingBroadcast.state = BroadcastRecord.IDLE;
3478 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003479 mPendingBroadcast = null;
3480 scheduleBroadcastsLocked();
3481 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003482 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003483 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003484 }
3485 }
3486
3487 private final boolean attachApplicationLocked(IApplicationThread thread,
3488 int pid) {
3489
3490 // Find the application record that is being attached... either via
3491 // the pid if we are running in multiple processes, or just pull the
3492 // next app record if we are emulating process with anonymous threads.
3493 ProcessRecord app;
3494 if (pid != MY_PID && pid >= 0) {
3495 synchronized (mPidsSelfLocked) {
3496 app = mPidsSelfLocked.get(pid);
3497 }
3498 } else if (mStartingProcesses.size() > 0) {
3499 app = mStartingProcesses.remove(0);
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07003500 app.setPid(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003501 } else {
3502 app = null;
3503 }
3504
3505 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003506 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003507 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003508 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003509 if (pid > 0 && pid != MY_PID) {
3510 Process.killProcess(pid);
3511 } else {
3512 try {
3513 thread.scheduleExit();
3514 } catch (Exception e) {
3515 // Ignore exceptions.
3516 }
3517 }
3518 return false;
3519 }
3520
3521 // If this application record is still attached to a previous
3522 // process, clean it up now.
3523 if (app.thread != null) {
3524 handleAppDiedLocked(app, true);
3525 }
3526
3527 // Tell the process all about itself.
3528
Joe Onorato8a9b2202010-02-26 18:56:32 -08003529 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003530 TAG, "Binding process pid " + pid + " to record " + app);
3531
3532 String processName = app.processName;
3533 try {
3534 thread.asBinder().linkToDeath(new AppDeathRecipient(
3535 app, pid, thread), 0);
3536 } catch (RemoteException e) {
3537 app.resetPackageList();
3538 startProcessLocked(app, "link fail", processName);
3539 return false;
3540 }
3541
Doug Zongker2bec3d42009-12-04 12:52:44 -08003542 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003543
3544 app.thread = thread;
3545 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08003546 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
3547 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003548 app.forcingToForeground = null;
3549 app.foregroundServices = false;
3550 app.debugging = false;
3551
3552 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3553
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003554 boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003555 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003556
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003557 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003558 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003559 }
3560
Joe Onorato8a9b2202010-02-26 18:56:32 -08003561 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003562 TAG, "New app record " + app
3563 + " thread=" + thread.asBinder() + " pid=" + pid);
3564 try {
3565 int testMode = IApplicationThread.DEBUG_OFF;
3566 if (mDebugApp != null && mDebugApp.equals(processName)) {
3567 testMode = mWaitForDebugger
3568 ? IApplicationThread.DEBUG_WAIT
3569 : IApplicationThread.DEBUG_ON;
3570 app.debugging = true;
3571 if (mDebugTransient) {
3572 mDebugApp = mOrigDebugApp;
3573 mWaitForDebugger = mOrigWaitForDebugger;
3574 }
3575 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003576
Christopher Tate181fafa2009-05-14 11:12:14 -07003577 // If the app is being launched for restore or full backup, set it up specially
3578 boolean isRestrictedBackupMode = false;
3579 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
3580 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
3581 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
3582 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003583
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07003584 ensurePackageDexOpt(app.instrumentationInfo != null
3585 ? app.instrumentationInfo.packageName
3586 : app.info.packageName);
3587 if (app.instrumentationClass != null) {
3588 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003589 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003590 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003591 + processName + " with config " + mConfiguration);
Dianne Hackborn1655be42009-05-08 14:29:01 -07003592 thread.bindApplication(processName, app.instrumentationInfo != null
3593 ? app.instrumentationInfo : app.info, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003594 app.instrumentationClass, app.instrumentationProfileFile,
3595 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003596 isRestrictedBackupMode || !normalMode,
Svetoslav Ganov54d068e2011-03-02 12:58:40 -08003597 mConfiguration, getCommonServicesLocked(),
3598 mCoreSettingsObserver.getCoreSettingsLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003599 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003600 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003601 } catch (Exception e) {
3602 // todo: Yikes! What should we do? For now we will try to
3603 // start another process, but that could easily get us in
3604 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08003605 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003606
3607 app.resetPackageList();
3608 startProcessLocked(app, "bind fail", processName);
3609 return false;
3610 }
3611
3612 // Remove this record from the list of starting applications.
3613 mPersistentStartingProcesses.remove(app);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003614 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
3615 "Attach application locked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003616 mProcessesOnHold.remove(app);
3617
3618 boolean badApp = false;
3619 boolean didSomething = false;
3620
3621 // See if the top visible activity is waiting to run in this process...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003622 ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07003623 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003624 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
3625 && processName.equals(hr.processName)) {
3626 try {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003627 if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003628 didSomething = true;
3629 }
3630 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003631 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003632 + hr.intent.getComponent().flattenToShortString(), e);
3633 badApp = true;
3634 }
3635 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003636 mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003637 }
3638 }
3639
3640 // Find any services that should be running in this process...
3641 if (!badApp && mPendingServices.size() > 0) {
3642 ServiceRecord sr = null;
3643 try {
3644 for (int i=0; i<mPendingServices.size(); i++) {
3645 sr = mPendingServices.get(i);
3646 if (app.info.uid != sr.appInfo.uid
3647 || !processName.equals(sr.processName)) {
3648 continue;
3649 }
3650
3651 mPendingServices.remove(i);
3652 i--;
3653 realStartServiceLocked(sr, app);
3654 didSomething = true;
3655 }
3656 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003657 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003658 + sr.shortName, e);
3659 badApp = true;
3660 }
3661 }
3662
3663 // Check if the next broadcast receiver is in this process...
3664 BroadcastRecord br = mPendingBroadcast;
3665 if (!badApp && br != null && br.curApp == app) {
3666 try {
3667 mPendingBroadcast = null;
3668 processCurBroadcastLocked(br, app);
3669 didSomething = true;
3670 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003671 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003672 + br.curComponent.flattenToShortString(), e);
3673 badApp = true;
Jeff Brown4d94a762010-09-23 11:33:28 -07003674 logBroadcastReceiverDiscardLocked(br);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003675 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
3676 br.resultExtras, br.resultAbort, true);
3677 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01003678 // We need to reset the state if we fails to start the receiver.
3679 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003680 }
3681 }
3682
Christopher Tate181fafa2009-05-14 11:12:14 -07003683 // Check whether the next backup agent is in this process...
3684 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003685 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003686 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07003687 try {
3688 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
3689 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003690 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07003691 e.printStackTrace();
3692 }
3693 }
3694
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003695 if (badApp) {
3696 // todo: Also need to kill application to deal with all
3697 // kinds of exceptions.
3698 handleAppDiedLocked(app, false);
3699 return false;
3700 }
3701
3702 if (!didSomething) {
3703 updateOomAdjLocked();
3704 }
3705
3706 return true;
3707 }
3708
3709 public final void attachApplication(IApplicationThread thread) {
3710 synchronized (this) {
3711 int callingPid = Binder.getCallingPid();
3712 final long origId = Binder.clearCallingIdentity();
3713 attachApplicationLocked(thread, callingPid);
3714 Binder.restoreCallingIdentity(origId);
3715 }
3716 }
3717
Dianne Hackborne88846e2009-09-30 21:34:25 -07003718 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003719 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003720 mMainStack.activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003721 Binder.restoreCallingIdentity(origId);
3722 }
3723
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003724 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003725 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003726 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003727 mWindowManager.enableScreenAfterBoot();
3728 }
3729
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003730 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003731 IntentFilter pkgFilter = new IntentFilter();
3732 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
3733 pkgFilter.addDataScheme("package");
3734 mContext.registerReceiver(new BroadcastReceiver() {
3735 @Override
3736 public void onReceive(Context context, Intent intent) {
3737 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
3738 if (pkgs != null) {
3739 for (String pkg : pkgs) {
Vairavan Srinivasan61f07652010-07-22 13:36:40 -07003740 synchronized (ActivityManagerService.this) {
3741 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
3742 setResultCode(Activity.RESULT_OK);
3743 return;
3744 }
3745 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003746 }
3747 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003748 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003749 }, pkgFilter);
3750
3751 synchronized (this) {
3752 // Ensure that any processes we had put on hold are now started
3753 // up.
3754 final int NP = mProcessesOnHold.size();
3755 if (NP > 0) {
3756 ArrayList<ProcessRecord> procs =
3757 new ArrayList<ProcessRecord>(mProcessesOnHold);
3758 for (int ip=0; ip<NP; ip++) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003759 if (DEBUG_PROCESSES) Slog.v(TAG, "Starting process on hold: "
3760 + procs.get(ip));
3761 startProcessLocked(procs.get(ip), "on-hold", null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003762 }
3763 }
3764
3765 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07003766 // Start looking for apps that are abusing wake locks.
3767 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07003768 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003769 // Tell anyone interested that we are done booting!
Dianne Hackbornf4c454b2010-08-11 12:47:41 -07003770 SystemProperties.set("sys.boot_completed", "1");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003771 broadcastIntentLocked(null, null,
3772 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
3773 null, null, 0, null, null,
3774 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
3775 false, false, MY_PID, Process.SYSTEM_UID);
3776 }
3777 }
3778 }
3779
3780 final void ensureBootCompleted() {
3781 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003782 boolean enableScreen;
3783 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003784 booting = mBooting;
3785 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003786 enableScreen = !mBooted;
3787 mBooted = true;
3788 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003789
3790 if (booting) {
3791 finishBooting();
3792 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003793
3794 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003795 enableScreenAfterBoot();
3796 }
3797 }
3798
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08003799 public final void activityPaused(IBinder token) {
3800 final long origId = Binder.clearCallingIdentity();
3801 mMainStack.activityPaused(token, false);
3802 Binder.restoreCallingIdentity(origId);
3803 }
3804
3805 public final void activityStopped(IBinder token, Bundle icicle, Bitmap thumbnail,
3806 CharSequence description) {
3807 if (localLOGV) Slog.v(
3808 TAG, "Activity stopped: token=" + token);
3809
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003810 // Refuse possible leaked file descriptors
3811 if (icicle != null && icicle.hasFileDescriptors()) {
3812 throw new IllegalArgumentException("File descriptors passed in Bundle");
3813 }
3814
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003815 ActivityRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003816
3817 final long origId = Binder.clearCallingIdentity();
3818
3819 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003820 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003821 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003822 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08003823 r.icicle = icicle;
3824 r.haveState = true;
3825 if (thumbnail != null) {
3826 r.thumbnail = thumbnail;
Dianne Hackbornd2835932010-12-13 16:28:46 -08003827 if (r.task != null) {
3828 r.task.lastThumbnail = r.thumbnail;
3829 }
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08003830 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003831 r.description = description;
Dianne Hackbornd2835932010-12-13 16:28:46 -08003832 if (r.task != null) {
3833 r.task.lastDescription = r.description;
3834 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003835 r.stopped = true;
3836 r.state = ActivityState.STOPPED;
3837 if (!r.finishing) {
3838 if (r.configDestroy) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003839 r.stack.destroyActivityLocked(r, true);
3840 r.stack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003841 }
3842 }
3843 }
3844 }
3845
3846 if (r != null) {
3847 sendPendingThumbnail(r, null, null, null, false);
3848 }
3849
3850 trimApplications();
3851
3852 Binder.restoreCallingIdentity(origId);
3853 }
3854
3855 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003856 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003857 mMainStack.activityDestroyed(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003858 }
3859
3860 public String getCallingPackage(IBinder token) {
3861 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003862 ActivityRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07003863 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003864 }
3865 }
3866
3867 public ComponentName getCallingActivity(IBinder token) {
3868 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003869 ActivityRecord r = getCallingRecordLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003870 return r != null ? r.intent.getComponent() : null;
3871 }
3872 }
3873
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003874 private ActivityRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003875 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003876 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003877 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003878 if (r != null) {
3879 return r.resultTo;
3880 }
3881 }
3882 return null;
3883 }
3884
3885 public ComponentName getActivityClassForToken(IBinder token) {
3886 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003887 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003888 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003889 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003890 return r.intent.getComponent();
3891 }
3892 return null;
3893 }
3894 }
3895
3896 public String getPackageForToken(IBinder token) {
3897 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003898 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003899 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003900 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003901 return r.packageName;
3902 }
3903 return null;
3904 }
3905 }
3906
3907 public IIntentSender getIntentSender(int type,
3908 String packageName, IBinder token, String resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003909 int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003910 // Refuse possible leaked file descriptors
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003911 if (intents != null) {
3912 if (intents.length < 1) {
3913 throw new IllegalArgumentException("Intents array length must be >= 1");
3914 }
3915 for (int i=0; i<intents.length; i++) {
3916 Intent intent = intents[i];
3917 if (intent == null) {
3918 throw new IllegalArgumentException("Null intent at index " + i);
3919 }
3920 if (intent.hasFileDescriptors()) {
3921 throw new IllegalArgumentException("File descriptors passed in Intent");
3922 }
3923 if (type == INTENT_SENDER_BROADCAST &&
3924 (intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
3925 throw new IllegalArgumentException(
3926 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
3927 }
3928 intents[i] = new Intent(intent);
3929 }
3930 if (resolvedTypes != null && resolvedTypes.length != intents.length) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003931 throw new IllegalArgumentException(
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003932 "Intent array length does not match resolvedTypes length");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003933 }
3934 }
3935
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003936 synchronized(this) {
3937 int callingUid = Binder.getCallingUid();
3938 try {
3939 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
3940 Process.supportsProcesses()) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003941 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003942 .getPackageUid(packageName);
3943 if (uid != Binder.getCallingUid()) {
3944 String msg = "Permission Denial: getIntentSender() from pid="
3945 + Binder.getCallingPid()
3946 + ", uid=" + Binder.getCallingUid()
3947 + ", (need uid=" + uid + ")"
3948 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003949 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003950 throw new SecurityException(msg);
3951 }
3952 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003953
3954 return getIntentSenderLocked(type, packageName, callingUid,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003955 token, resultWho, requestCode, intents, resolvedTypes, flags);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003956
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003957 } catch (RemoteException e) {
3958 throw new SecurityException(e);
3959 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003960 }
3961 }
3962
3963 IIntentSender getIntentSenderLocked(int type,
3964 String packageName, int callingUid, IBinder token, String resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003965 int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003966 ActivityRecord activity = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07003967 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003968 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003969 if (index < 0) {
3970 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003971 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003972 activity = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003973 if (activity.finishing) {
3974 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003975 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003976 }
3977
3978 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
3979 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
3980 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
3981 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
3982 |PendingIntent.FLAG_UPDATE_CURRENT);
3983
3984 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
3985 type, packageName, activity, resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003986 requestCode, intents, resolvedTypes, flags);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003987 WeakReference<PendingIntentRecord> ref;
3988 ref = mIntentSenderRecords.get(key);
3989 PendingIntentRecord rec = ref != null ? ref.get() : null;
3990 if (rec != null) {
3991 if (!cancelCurrent) {
3992 if (updateCurrent) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003993 if (rec.key.requestIntent != null) {
3994 rec.key.requestIntent.replaceExtras(intents != null ? intents[0] : null);
3995 }
3996 if (intents != null) {
3997 intents[intents.length-1] = rec.key.requestIntent;
3998 rec.key.allIntents = intents;
3999 rec.key.allResolvedTypes = resolvedTypes;
4000 } else {
4001 rec.key.allIntents = null;
4002 rec.key.allResolvedTypes = null;
4003 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004004 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004005 return rec;
4006 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004007 rec.canceled = true;
4008 mIntentSenderRecords.remove(key);
4009 }
4010 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004011 return rec;
4012 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004013 rec = new PendingIntentRecord(this, key, callingUid);
4014 mIntentSenderRecords.put(key, rec.ref);
4015 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
4016 if (activity.pendingResults == null) {
4017 activity.pendingResults
4018 = new HashSet<WeakReference<PendingIntentRecord>>();
4019 }
4020 activity.pendingResults.add(rec.ref);
4021 }
4022 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004023 }
4024
4025 public void cancelIntentSender(IIntentSender sender) {
4026 if (!(sender instanceof PendingIntentRecord)) {
4027 return;
4028 }
4029 synchronized(this) {
4030 PendingIntentRecord rec = (PendingIntentRecord)sender;
4031 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004032 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004033 .getPackageUid(rec.key.packageName);
4034 if (uid != Binder.getCallingUid()) {
4035 String msg = "Permission Denial: cancelIntentSender() from pid="
4036 + Binder.getCallingPid()
4037 + ", uid=" + Binder.getCallingUid()
4038 + " is not allowed to cancel packges "
4039 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004040 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004041 throw new SecurityException(msg);
4042 }
4043 } catch (RemoteException e) {
4044 throw new SecurityException(e);
4045 }
4046 cancelIntentSenderLocked(rec, true);
4047 }
4048 }
4049
4050 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
4051 rec.canceled = true;
4052 mIntentSenderRecords.remove(rec.key);
4053 if (cleanActivity && rec.key.activity != null) {
4054 rec.key.activity.pendingResults.remove(rec.ref);
4055 }
4056 }
4057
4058 public String getPackageForIntentSender(IIntentSender pendingResult) {
4059 if (!(pendingResult instanceof PendingIntentRecord)) {
4060 return null;
4061 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07004062 try {
4063 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
4064 return res.key.packageName;
4065 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004066 }
4067 return null;
4068 }
4069
4070 public void setProcessLimit(int max) {
4071 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4072 "setProcessLimit()");
4073 mProcessLimit = max;
4074 }
4075
4076 public int getProcessLimit() {
4077 return mProcessLimit;
4078 }
4079
4080 void foregroundTokenDied(ForegroundToken token) {
4081 synchronized (ActivityManagerService.this) {
4082 synchronized (mPidsSelfLocked) {
4083 ForegroundToken cur
4084 = mForegroundProcesses.get(token.pid);
4085 if (cur != token) {
4086 return;
4087 }
4088 mForegroundProcesses.remove(token.pid);
4089 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
4090 if (pr == null) {
4091 return;
4092 }
4093 pr.forcingToForeground = null;
4094 pr.foregroundServices = false;
4095 }
4096 updateOomAdjLocked();
4097 }
4098 }
4099
4100 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
4101 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4102 "setProcessForeground()");
4103 synchronized(this) {
4104 boolean changed = false;
4105
4106 synchronized (mPidsSelfLocked) {
4107 ProcessRecord pr = mPidsSelfLocked.get(pid);
4108 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004109 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004110 return;
4111 }
4112 ForegroundToken oldToken = mForegroundProcesses.get(pid);
4113 if (oldToken != null) {
4114 oldToken.token.unlinkToDeath(oldToken, 0);
4115 mForegroundProcesses.remove(pid);
4116 pr.forcingToForeground = null;
4117 changed = true;
4118 }
4119 if (isForeground && token != null) {
4120 ForegroundToken newToken = new ForegroundToken() {
4121 public void binderDied() {
4122 foregroundTokenDied(this);
4123 }
4124 };
4125 newToken.pid = pid;
4126 newToken.token = token;
4127 try {
4128 token.linkToDeath(newToken, 0);
4129 mForegroundProcesses.put(pid, newToken);
4130 pr.forcingToForeground = token;
4131 changed = true;
4132 } catch (RemoteException e) {
4133 // If the process died while doing this, we will later
4134 // do the cleanup with the process death link.
4135 }
4136 }
4137 }
4138
4139 if (changed) {
4140 updateOomAdjLocked();
4141 }
4142 }
4143 }
4144
4145 // =========================================================
4146 // PERMISSIONS
4147 // =========================================================
4148
4149 static class PermissionController extends IPermissionController.Stub {
4150 ActivityManagerService mActivityManagerService;
4151 PermissionController(ActivityManagerService activityManagerService) {
4152 mActivityManagerService = activityManagerService;
4153 }
4154
4155 public boolean checkPermission(String permission, int pid, int uid) {
4156 return mActivityManagerService.checkPermission(permission, pid,
4157 uid) == PackageManager.PERMISSION_GRANTED;
4158 }
4159 }
4160
4161 /**
4162 * This can be called with or without the global lock held.
4163 */
4164 int checkComponentPermission(String permission, int pid, int uid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004165 int owningUid, boolean exported) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004166 // We might be performing an operation on behalf of an indirect binder
4167 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
4168 // client identity accordingly before proceeding.
4169 Identity tlsIdentity = sCallerIdentity.get();
4170 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004171 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004172 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
4173 uid = tlsIdentity.uid;
4174 pid = tlsIdentity.pid;
4175 }
4176
4177 // Root, system server and our own process get to do everything.
4178 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
4179 !Process.supportsProcesses()) {
4180 return PackageManager.PERMISSION_GRANTED;
4181 }
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004182 // If there is a uid that owns whatever is being accessed, it has
4183 // blanket access to it regardless of the permissions it requires.
4184 if (owningUid >= 0 && uid == owningUid) {
4185 return PackageManager.PERMISSION_GRANTED;
4186 }
4187 // If the target is not exported, then nobody else can get to it.
4188 if (!exported) {
4189 Slog.w(TAG, "Permission denied: checkComponentPermission() owningUid=" + owningUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004190 return PackageManager.PERMISSION_DENIED;
4191 }
4192 if (permission == null) {
4193 return PackageManager.PERMISSION_GRANTED;
4194 }
4195 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004196 return AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004197 .checkUidPermission(permission, uid);
4198 } catch (RemoteException e) {
4199 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004200 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004201 }
4202 return PackageManager.PERMISSION_DENIED;
4203 }
4204
4205 /**
4206 * As the only public entry point for permissions checking, this method
4207 * can enforce the semantic that requesting a check on a null global
4208 * permission is automatically denied. (Internally a null permission
4209 * string is used when calling {@link #checkComponentPermission} in cases
4210 * when only uid-based security is needed.)
4211 *
4212 * This can be called with or without the global lock held.
4213 */
4214 public int checkPermission(String permission, int pid, int uid) {
4215 if (permission == null) {
4216 return PackageManager.PERMISSION_DENIED;
4217 }
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004218 return checkComponentPermission(permission, pid, uid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004219 }
4220
4221 /**
4222 * Binder IPC calls go through the public entry point.
4223 * This can be called with or without the global lock held.
4224 */
4225 int checkCallingPermission(String permission) {
4226 return checkPermission(permission,
4227 Binder.getCallingPid(),
4228 Binder.getCallingUid());
4229 }
4230
4231 /**
4232 * This can be called with or without the global lock held.
4233 */
4234 void enforceCallingPermission(String permission, String func) {
4235 if (checkCallingPermission(permission)
4236 == PackageManager.PERMISSION_GRANTED) {
4237 return;
4238 }
4239
4240 String msg = "Permission Denial: " + func + " from pid="
4241 + Binder.getCallingPid()
4242 + ", uid=" + Binder.getCallingUid()
4243 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004244 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004245 throw new SecurityException(msg);
4246 }
4247
4248 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
Dianne Hackborn48058e82010-09-27 16:53:23 -07004249 ProviderInfo pi, Uri uri, int uid, int modeFlags) {
4250 boolean readPerm = (modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0;
4251 boolean writePerm = (modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0;
4252 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4253 "checkHoldingPermissionsLocked: uri=" + uri + " uid=" + uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004254 try {
Dianne Hackborn48058e82010-09-27 16:53:23 -07004255 // Is the component private from the target uid?
4256 final boolean prv = !pi.exported && pi.applicationInfo.uid != uid;
4257
4258 // Acceptable if the there is no read permission needed from the
4259 // target or the target is holding the read permission.
4260 if (!readPerm) {
4261 if ((!prv && pi.readPermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004262 (pm.checkUidPermission(pi.readPermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004263 == PackageManager.PERMISSION_GRANTED)) {
4264 readPerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004265 }
4266 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004267
4268 // Acceptable if the there is no write permission needed from the
4269 // target or the target is holding the read permission.
4270 if (!writePerm) {
4271 if (!prv && (pi.writePermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004272 (pm.checkUidPermission(pi.writePermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004273 == PackageManager.PERMISSION_GRANTED)) {
4274 writePerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004275 }
4276 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004277
4278 // Acceptable if there is a path permission matching the URI that
4279 // the target holds the permission on.
4280 PathPermission[] pps = pi.pathPermissions;
4281 if (pps != null && (!readPerm || !writePerm)) {
4282 final String path = uri.getPath();
4283 int i = pps.length;
4284 while (i > 0 && (!readPerm || !writePerm)) {
4285 i--;
4286 PathPermission pp = pps[i];
4287 if (!readPerm) {
4288 final String pprperm = pp.getReadPermission();
4289 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking read perm for "
4290 + pprperm + " for " + pp.getPath()
4291 + ": match=" + pp.match(path)
4292 + " check=" + pm.checkUidPermission(pprperm, uid));
4293 if (pprperm != null && pp.match(path) &&
4294 (pm.checkUidPermission(pprperm, uid)
4295 == PackageManager.PERMISSION_GRANTED)) {
4296 readPerm = true;
4297 }
4298 }
4299 if (!writePerm) {
4300 final String ppwperm = pp.getWritePermission();
4301 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking write perm "
4302 + ppwperm + " for " + pp.getPath()
4303 + ": match=" + pp.match(path)
4304 + " check=" + pm.checkUidPermission(ppwperm, uid));
4305 if (ppwperm != null && pp.match(path) &&
4306 (pm.checkUidPermission(ppwperm, uid)
4307 == PackageManager.PERMISSION_GRANTED)) {
4308 writePerm = true;
4309 }
4310 }
4311 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004312 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004313 } catch (RemoteException e) {
4314 return false;
4315 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004316
4317 return readPerm && writePerm;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004318 }
4319
4320 private final boolean checkUriPermissionLocked(Uri uri, int uid,
4321 int modeFlags) {
4322 // Root gets to do everything.
4323 if (uid == 0 || !Process.supportsProcesses()) {
4324 return true;
4325 }
4326 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
4327 if (perms == null) return false;
4328 UriPermission perm = perms.get(uri);
4329 if (perm == null) return false;
4330 return (modeFlags&perm.modeFlags) == modeFlags;
4331 }
4332
4333 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
4334 // Another redirected-binder-call permissions check as in
4335 // {@link checkComponentPermission}.
4336 Identity tlsIdentity = sCallerIdentity.get();
4337 if (tlsIdentity != null) {
4338 uid = tlsIdentity.uid;
4339 pid = tlsIdentity.pid;
4340 }
4341
4342 // Our own process gets to do everything.
4343 if (pid == MY_PID) {
4344 return PackageManager.PERMISSION_GRANTED;
4345 }
4346 synchronized(this) {
4347 return checkUriPermissionLocked(uri, uid, modeFlags)
4348 ? PackageManager.PERMISSION_GRANTED
4349 : PackageManager.PERMISSION_DENIED;
4350 }
4351 }
4352
Dianne Hackborn39792d22010-08-19 18:01:52 -07004353 /**
4354 * Check if the targetPkg can be granted permission to access uri by
4355 * the callingUid using the given modeFlags. Throws a security exception
4356 * if callingUid is not allowed to do this. Returns the uid of the target
4357 * if the URI permission grant should be performed; returns -1 if it is not
4358 * needed (for example targetPkg already has permission to access the URI).
4359 */
4360 int checkGrantUriPermissionLocked(int callingUid, String targetPkg,
4361 Uri uri, int modeFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004362 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4363 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4364 if (modeFlags == 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004365 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004366 }
4367
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004368 if (targetPkg != null) {
4369 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4370 "Checking grant " + targetPkg + " permission to " + uri);
4371 }
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004372
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004373 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004374
4375 // If this is not a content: uri, we can't do anything with it.
4376 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004377 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004378 "Can't grant URI permission for non-content URI: " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004379 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004380 }
4381
4382 String name = uri.getAuthority();
4383 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004384 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004385 if (cpr != null) {
4386 pi = cpr.info;
4387 } else {
4388 try {
4389 pi = pm.resolveContentProvider(name,
4390 PackageManager.GET_URI_PERMISSION_PATTERNS);
4391 } catch (RemoteException ex) {
4392 }
4393 }
4394 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004395 Slog.w(TAG, "No content provider found for: " + name);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004396 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004397 }
4398
4399 int targetUid;
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004400 if (targetPkg != null) {
4401 try {
4402 targetUid = pm.getPackageUid(targetPkg);
4403 if (targetUid < 0) {
4404 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4405 "Can't grant URI permission no uid for: " + targetPkg);
4406 return -1;
4407 }
4408 } catch (RemoteException ex) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004409 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004410 }
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004411 } else {
4412 targetUid = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004413 }
4414
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004415 if (targetUid >= 0) {
4416 // First... does the target actually need this permission?
4417 if (checkHoldingPermissionsLocked(pm, pi, uri, targetUid, modeFlags)) {
4418 // No need to grant the target this permission.
4419 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4420 "Target " + targetPkg + " already has full permission to " + uri);
4421 return -1;
4422 }
4423 } else {
4424 // First... there is no target package, so can anyone access it?
4425 boolean allowed = pi.exported;
4426 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4427 if (pi.readPermission != null) {
4428 allowed = false;
4429 }
4430 }
4431 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4432 if (pi.writePermission != null) {
4433 allowed = false;
4434 }
4435 }
4436 if (allowed) {
4437 return -1;
4438 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004439 }
4440
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004441 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004442 if (!pi.grantUriPermissions) {
4443 throw new SecurityException("Provider " + pi.packageName
4444 + "/" + pi.name
4445 + " does not allow granting of Uri permissions (uri "
4446 + uri + ")");
4447 }
4448 if (pi.uriPermissionPatterns != null) {
4449 final int N = pi.uriPermissionPatterns.length;
4450 boolean allowed = false;
4451 for (int i=0; i<N; i++) {
4452 if (pi.uriPermissionPatterns[i] != null
4453 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
4454 allowed = true;
4455 break;
4456 }
4457 }
4458 if (!allowed) {
4459 throw new SecurityException("Provider " + pi.packageName
4460 + "/" + pi.name
4461 + " does not allow granting of permission to path of Uri "
4462 + uri);
4463 }
4464 }
4465
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004466 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004467 // this uri?
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004468 if (callingUid != Process.myUid()) {
4469 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
4470 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4471 throw new SecurityException("Uid " + callingUid
4472 + " does not have permission to uri " + uri);
4473 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004474 }
4475 }
4476
Dianne Hackborn39792d22010-08-19 18:01:52 -07004477 return targetUid;
4478 }
4479
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004480 public int checkGrantUriPermission(int callingUid, String targetPkg,
4481 Uri uri, int modeFlags) {
4482 synchronized(this) {
4483 return checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4484 }
4485 }
4486
Dianne Hackborn39792d22010-08-19 18:01:52 -07004487 void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg,
4488 Uri uri, int modeFlags, UriPermissionOwner owner) {
4489 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4490 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4491 if (modeFlags == 0) {
4492 return;
4493 }
4494
4495 // So here we are: the caller has the assumed permission
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004496 // to the uri, and the target doesn't. Let's now give this to
4497 // the target.
4498
Joe Onorato8a9b2202010-02-26 18:56:32 -08004499 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004500 "Granting " + targetPkg + "/" + targetUid + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004501
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004502 HashMap<Uri, UriPermission> targetUris
4503 = mGrantedUriPermissions.get(targetUid);
4504 if (targetUris == null) {
4505 targetUris = new HashMap<Uri, UriPermission>();
4506 mGrantedUriPermissions.put(targetUid, targetUris);
4507 }
4508
4509 UriPermission perm = targetUris.get(uri);
4510 if (perm == null) {
4511 perm = new UriPermission(targetUid, uri);
4512 targetUris.put(uri, perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004513 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004514
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004515 perm.modeFlags |= modeFlags;
Dianne Hackborn39792d22010-08-19 18:01:52 -07004516 if (owner == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004517 perm.globalModeFlags |= modeFlags;
Vairavan Srinivasan91c12c22011-01-21 18:26:06 -08004518 } else {
4519 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4520 perm.readOwners.add(owner);
4521 owner.addReadPermission(perm);
4522 }
4523 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4524 perm.writeOwners.add(owner);
4525 owner.addWritePermission(perm);
4526 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004527 }
4528 }
4529
Dianne Hackborn39792d22010-08-19 18:01:52 -07004530 void grantUriPermissionLocked(int callingUid,
4531 String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) {
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004532 if (targetPkg == null) {
4533 throw new NullPointerException("targetPkg");
4534 }
4535
Dianne Hackborn39792d22010-08-19 18:01:52 -07004536 int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4537 if (targetUid < 0) {
4538 return;
4539 }
4540
4541 grantUriPermissionUncheckedLocked(targetUid, targetPkg, uri, modeFlags, owner);
4542 }
4543
4544 /**
4545 * Like checkGrantUriPermissionLocked, but takes an Intent.
4546 */
4547 int checkGrantUriPermissionFromIntentLocked(int callingUid,
4548 String targetPkg, Intent intent) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07004549 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004550 "Checking URI perm to " + (intent != null ? intent.getData() : null)
Dianne Hackbornb424b632010-08-18 15:59:05 -07004551 + " from " + intent + "; flags=0x"
4552 + Integer.toHexString(intent != null ? intent.getFlags() : 0));
4553
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004554 if (targetPkg == null) {
4555 throw new NullPointerException("targetPkg");
4556 }
4557
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004558 if (intent == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004559 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004560 }
4561 Uri data = intent.getData();
4562 if (data == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004563 return -1;
4564 }
4565 return checkGrantUriPermissionLocked(callingUid, targetPkg, data,
4566 intent.getFlags());
4567 }
4568
4569 /**
4570 * Like grantUriPermissionUncheckedLocked, but takes an Intent.
4571 */
4572 void grantUriPermissionUncheckedFromIntentLocked(int targetUid,
4573 String targetPkg, Intent intent, UriPermissionOwner owner) {
4574 grantUriPermissionUncheckedLocked(targetUid, targetPkg, intent.getData(),
4575 intent.getFlags(), owner);
4576 }
4577
4578 void grantUriPermissionFromIntentLocked(int callingUid,
4579 String targetPkg, Intent intent, UriPermissionOwner owner) {
4580 int targetUid = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg, intent);
4581 if (targetUid < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004582 return;
4583 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07004584
4585 grantUriPermissionUncheckedFromIntentLocked(targetUid, targetPkg, intent, owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004586 }
4587
4588 public void grantUriPermission(IApplicationThread caller, String targetPkg,
4589 Uri uri, int modeFlags) {
4590 synchronized(this) {
4591 final ProcessRecord r = getRecordForAppLocked(caller);
4592 if (r == null) {
4593 throw new SecurityException("Unable to find app for caller "
4594 + caller
4595 + " when granting permission to uri " + uri);
4596 }
4597 if (targetPkg == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004598 throw new IllegalArgumentException("null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004599 }
4600 if (uri == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004601 throw new IllegalArgumentException("null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004602 }
4603
4604 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
4605 null);
4606 }
4607 }
4608
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004609 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004610 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
4611 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
4612 HashMap<Uri, UriPermission> perms
4613 = mGrantedUriPermissions.get(perm.uid);
4614 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004615 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004616 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004617 perms.remove(perm.uri);
4618 if (perms.size() == 0) {
4619 mGrantedUriPermissions.remove(perm.uid);
4620 }
4621 }
4622 }
4623 }
4624
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004625 private void revokeUriPermissionLocked(int callingUid, Uri uri,
4626 int modeFlags) {
4627 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4628 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4629 if (modeFlags == 0) {
4630 return;
4631 }
4632
Joe Onorato8a9b2202010-02-26 18:56:32 -08004633 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004634 "Revoking all granted permissions to " + uri);
4635
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004636 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004637
4638 final String authority = uri.getAuthority();
4639 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004640 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004641 if (cpr != null) {
4642 pi = cpr.info;
4643 } else {
4644 try {
4645 pi = pm.resolveContentProvider(authority,
4646 PackageManager.GET_URI_PERMISSION_PATTERNS);
4647 } catch (RemoteException ex) {
4648 }
4649 }
4650 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004651 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004652 return;
4653 }
4654
4655 // Does the caller have this permission on the URI?
Dianne Hackborn48058e82010-09-27 16:53:23 -07004656 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004657 // Right now, if you are not the original owner of the permission,
4658 // you are not allowed to revoke it.
4659 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4660 throw new SecurityException("Uid " + callingUid
4661 + " does not have permission to uri " + uri);
4662 //}
4663 }
4664
4665 // Go through all of the permissions and remove any that match.
4666 final List<String> SEGMENTS = uri.getPathSegments();
4667 if (SEGMENTS != null) {
4668 final int NS = SEGMENTS.size();
4669 int N = mGrantedUriPermissions.size();
4670 for (int i=0; i<N; i++) {
4671 HashMap<Uri, UriPermission> perms
4672 = mGrantedUriPermissions.valueAt(i);
4673 Iterator<UriPermission> it = perms.values().iterator();
4674 toploop:
4675 while (it.hasNext()) {
4676 UriPermission perm = it.next();
4677 Uri targetUri = perm.uri;
4678 if (!authority.equals(targetUri.getAuthority())) {
4679 continue;
4680 }
4681 List<String> targetSegments = targetUri.getPathSegments();
4682 if (targetSegments == null) {
4683 continue;
4684 }
4685 if (targetSegments.size() < NS) {
4686 continue;
4687 }
4688 for (int j=0; j<NS; j++) {
4689 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
4690 continue toploop;
4691 }
4692 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004693 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004694 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004695 perm.clearModes(modeFlags);
4696 if (perm.modeFlags == 0) {
4697 it.remove();
4698 }
4699 }
4700 if (perms.size() == 0) {
4701 mGrantedUriPermissions.remove(
4702 mGrantedUriPermissions.keyAt(i));
4703 N--;
4704 i--;
4705 }
4706 }
4707 }
4708 }
4709
4710 public void revokeUriPermission(IApplicationThread caller, Uri uri,
4711 int modeFlags) {
4712 synchronized(this) {
4713 final ProcessRecord r = getRecordForAppLocked(caller);
4714 if (r == null) {
4715 throw new SecurityException("Unable to find app for caller "
4716 + caller
4717 + " when revoking permission to uri " + uri);
4718 }
4719 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004720 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004721 return;
4722 }
4723
4724 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4725 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4726 if (modeFlags == 0) {
4727 return;
4728 }
4729
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004730 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004731
4732 final String authority = uri.getAuthority();
4733 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004734 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004735 if (cpr != null) {
4736 pi = cpr.info;
4737 } else {
4738 try {
4739 pi = pm.resolveContentProvider(authority,
4740 PackageManager.GET_URI_PERMISSION_PATTERNS);
4741 } catch (RemoteException ex) {
4742 }
4743 }
4744 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004745 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004746 return;
4747 }
4748
4749 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
4750 }
4751 }
4752
Dianne Hackborn7e269642010-08-25 19:50:20 -07004753 @Override
4754 public IBinder newUriPermissionOwner(String name) {
4755 synchronized(this) {
4756 UriPermissionOwner owner = new UriPermissionOwner(this, name);
4757 return owner.getExternalTokenLocked();
4758 }
4759 }
4760
4761 @Override
4762 public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg,
4763 Uri uri, int modeFlags) {
4764 synchronized(this) {
4765 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4766 if (owner == null) {
4767 throw new IllegalArgumentException("Unknown owner: " + token);
4768 }
4769 if (fromUid != Binder.getCallingUid()) {
4770 if (Binder.getCallingUid() != Process.myUid()) {
4771 // Only system code can grant URI permissions on behalf
4772 // of other users.
4773 throw new SecurityException("nice try");
4774 }
4775 }
4776 if (targetPkg == null) {
4777 throw new IllegalArgumentException("null target");
4778 }
4779 if (uri == null) {
4780 throw new IllegalArgumentException("null uri");
4781 }
4782
4783 grantUriPermissionLocked(fromUid, targetPkg, uri, modeFlags, owner);
4784 }
4785 }
4786
4787 @Override
4788 public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode) {
4789 synchronized(this) {
4790 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4791 if (owner == null) {
4792 throw new IllegalArgumentException("Unknown owner: " + token);
4793 }
4794
4795 if (uri == null) {
4796 owner.removeUriPermissionsLocked(mode);
4797 } else {
4798 owner.removeUriPermissionLocked(uri, mode);
4799 }
4800 }
4801 }
4802
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004803 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
4804 synchronized (this) {
4805 ProcessRecord app =
4806 who != null ? getRecordForAppLocked(who) : null;
4807 if (app == null) return;
4808
4809 Message msg = Message.obtain();
4810 msg.what = WAIT_FOR_DEBUGGER_MSG;
4811 msg.obj = app;
4812 msg.arg1 = waiting ? 1 : 0;
4813 mHandler.sendMessage(msg);
4814 }
4815 }
4816
4817 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
4818 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08004819 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004820 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08004821 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004822 }
4823
4824 // =========================================================
4825 // TASK MANAGEMENT
4826 // =========================================================
4827
4828 public List getTasks(int maxNum, int flags,
4829 IThumbnailReceiver receiver) {
4830 ArrayList list = new ArrayList();
4831
4832 PendingThumbnailsRecord pending = null;
4833 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004834 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004835
4836 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004837 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004838 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
4839 + ", receiver=" + receiver);
4840
4841 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
4842 != PackageManager.PERMISSION_GRANTED) {
4843 if (receiver != null) {
4844 // If the caller wants to wait for pending thumbnails,
4845 // it ain't gonna get them.
4846 try {
4847 receiver.finished();
4848 } catch (RemoteException ex) {
4849 }
4850 }
4851 String msg = "Permission Denial: getTasks() from pid="
4852 + Binder.getCallingPid()
4853 + ", uid=" + Binder.getCallingUid()
4854 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004855 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004856 throw new SecurityException(msg);
4857 }
4858
Dianne Hackbornd2835932010-12-13 16:28:46 -08004859 final boolean canReadFb = (flags&ActivityManager.TASKS_GET_THUMBNAILS) != 0
4860 && checkCallingPermission(
4861 android.Manifest.permission.READ_FRAME_BUFFER)
4862 == PackageManager.PERMISSION_GRANTED;
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08004863
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004864 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004865 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004866 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004867 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004868 CharSequence topDescription = null;
4869 TaskRecord curTask = null;
4870 int numActivities = 0;
4871 int numRunning = 0;
4872 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004873 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004874 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004875 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004876
4877 // Initialize state for next task if needed.
4878 if (top == null ||
4879 (top.state == ActivityState.INITIALIZING
4880 && top.task == r.task)) {
4881 top = r;
4882 topDescription = r.description;
4883 curTask = r.task;
4884 numActivities = numRunning = 0;
4885 }
4886
4887 // Add 'r' into the current task.
4888 numActivities++;
4889 if (r.app != null && r.app.thread != null) {
4890 numRunning++;
4891 }
4892 if (topDescription == null) {
4893 topDescription = r.description;
4894 }
4895
Joe Onorato8a9b2202010-02-26 18:56:32 -08004896 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004897 TAG, r.intent.getComponent().flattenToShortString()
4898 + ": task=" + r.task);
4899
4900 // If the next one is a different task, generate a new
4901 // TaskInfo entry for what we have.
4902 if (next == null || next.task != curTask) {
4903 ActivityManager.RunningTaskInfo ci
4904 = new ActivityManager.RunningTaskInfo();
4905 ci.id = curTask.taskId;
4906 ci.baseActivity = r.intent.getComponent();
4907 ci.topActivity = top.intent.getComponent();
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08004908 if (canReadFb) {
4909 if (top.thumbnail != null) {
4910 ci.thumbnail = top.thumbnail;
4911 } else if (top.state == ActivityState.RESUMED) {
Dianne Hackbornd2835932010-12-13 16:28:46 -08004912 ci.thumbnail = top.stack.screenshotActivities(top);
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08004913 }
4914 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004915 ci.description = topDescription;
4916 ci.numActivities = numActivities;
4917 ci.numRunning = numRunning;
4918 //System.out.println(
4919 // "#" + maxNum + ": " + " descr=" + ci.description);
4920 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004921 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004922 TAG, "State=" + top.state + "Idle=" + top.idle
4923 + " app=" + top.app
4924 + " thr=" + (top.app != null ? top.app.thread : null));
4925 if (top.state == ActivityState.RESUMED
4926 || top.state == ActivityState.PAUSING) {
4927 if (top.idle && top.app != null
4928 && top.app.thread != null) {
4929 topRecord = top;
4930 topThumbnail = top.app.thread;
4931 } else {
4932 top.thumbnailNeeded = true;
4933 }
4934 }
4935 if (pending == null) {
4936 pending = new PendingThumbnailsRecord(receiver);
4937 }
4938 pending.pendingRecords.add(top);
4939 }
4940 list.add(ci);
4941 maxNum--;
4942 top = null;
4943 }
4944 }
4945
4946 if (pending != null) {
4947 mPendingThumbnails.add(pending);
4948 }
4949 }
4950
Joe Onorato8a9b2202010-02-26 18:56:32 -08004951 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004952
4953 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004954 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004955 try {
4956 topThumbnail.requestThumbnail(topRecord);
4957 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004958 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004959 sendPendingThumbnail(null, topRecord, null, null, true);
4960 }
4961 }
4962
4963 if (pending == null && receiver != null) {
4964 // In this case all thumbnails were available and the client
4965 // is being asked to be told when the remaining ones come in...
4966 // which is unusually, since the top-most currently running
4967 // activity should never have a canned thumbnail! Oh well.
4968 try {
4969 receiver.finished();
4970 } catch (RemoteException ex) {
4971 }
4972 }
4973
4974 return list;
4975 }
4976
4977 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
4978 int flags) {
4979 synchronized (this) {
4980 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
4981 "getRecentTasks()");
4982
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004983 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004984
Dianne Hackbornd2835932010-12-13 16:28:46 -08004985 ActivityRecord resumed = mMainStack.mResumedActivity;
4986
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004987 final int N = mRecentTasks.size();
4988 ArrayList<ActivityManager.RecentTaskInfo> res
4989 = new ArrayList<ActivityManager.RecentTaskInfo>(
4990 maxNum < N ? maxNum : N);
4991 for (int i=0; i<N && maxNum > 0; i++) {
4992 TaskRecord tr = mRecentTasks.get(i);
4993 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
4994 || (tr.intent == null)
4995 || ((tr.intent.getFlags()
4996 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
4997 ActivityManager.RecentTaskInfo rti
4998 = new ActivityManager.RecentTaskInfo();
4999 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
Dianne Hackbornd94df452011-02-16 18:53:31 -08005000 rti.persistentId = tr.taskId;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005001 rti.baseIntent = new Intent(
5002 tr.intent != null ? tr.intent : tr.affinityIntent);
5003 rti.origActivity = tr.origActivity;
Dianne Hackbornd2835932010-12-13 16:28:46 -08005004 rti.description = tr.lastDescription;
5005
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07005006 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
5007 // Check whether this activity is currently available.
5008 try {
5009 if (rti.origActivity != null) {
5010 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
5011 continue;
5012 }
5013 } else if (rti.baseIntent != null) {
5014 if (pm.queryIntentActivities(rti.baseIntent,
5015 null, 0) == null) {
5016 continue;
5017 }
5018 }
5019 } catch (RemoteException e) {
5020 // Will never happen.
5021 }
5022 }
5023
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005024 res.add(rti);
5025 maxNum--;
5026 }
5027 }
5028 return res;
5029 }
5030 }
5031
Dianne Hackbornd94df452011-02-16 18:53:31 -08005032 public Bitmap getTaskThumbnail(int id) {
5033 synchronized (this) {
5034 enforceCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER,
5035 "getTaskThumbnail()");
5036 ActivityRecord resumed = mMainStack.mResumedActivity;
5037 final int N = mRecentTasks.size();
5038 for (int i=0; i<N; i++) {
5039 TaskRecord tr = mRecentTasks.get(i);
5040 if (tr.taskId == id) {
5041 if (resumed != null && resumed.task == tr) {
5042 return resumed.stack.screenshotActivities(resumed);
5043 } else {
5044 return tr.lastThumbnail;
5045 }
5046 }
5047 }
5048 }
5049 return null;
5050 }
5051
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005052 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
5053 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005054 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005055 TaskRecord jt = startTask;
5056
5057 // First look backwards
5058 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005059 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005060 if (r.task != jt) {
5061 jt = r.task;
5062 if (affinity.equals(jt.affinity)) {
5063 return j;
5064 }
5065 }
5066 }
5067
5068 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005069 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005070 jt = startTask;
5071 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005072 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005073 if (r.task != jt) {
5074 if (affinity.equals(jt.affinity)) {
5075 return j;
5076 }
5077 jt = r.task;
5078 }
5079 }
5080
5081 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005082 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005083 return N-1;
5084 }
5085
5086 return -1;
5087 }
5088
5089 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005090 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005091 */
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005092 public void moveTaskToFront(int task, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005093 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5094 "moveTaskToFront()");
5095
5096 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005097 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5098 Binder.getCallingUid(), "Task to front")) {
5099 return;
5100 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005101 final long origId = Binder.clearCallingIdentity();
5102 try {
5103 int N = mRecentTasks.size();
5104 for (int i=0; i<N; i++) {
5105 TaskRecord tr = mRecentTasks.get(i);
5106 if (tr.taskId == task) {
Dianne Hackbornd94df452011-02-16 18:53:31 -08005107 if ((flags&ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
5108 mMainStack.mUserLeaving = true;
5109 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005110 if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
5111 // Caller wants the home activity moved with it. To accomplish this,
5112 // we'll just move the home task to the top first.
5113 mMainStack.moveHomeToFrontLocked();
5114 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005115 mMainStack.moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005116 return;
5117 }
5118 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005119 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
5120 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005121 if (hr.task.taskId == task) {
Dianne Hackbornd94df452011-02-16 18:53:31 -08005122 if ((flags&ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
5123 mMainStack.mUserLeaving = true;
5124 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005125 if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
5126 // Caller wants the home activity moved with it. To accomplish this,
5127 // we'll just move the home task to the top first.
5128 mMainStack.moveHomeToFrontLocked();
5129 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005130 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005131 return;
5132 }
5133 }
5134 } finally {
5135 Binder.restoreCallingIdentity(origId);
5136 }
5137 }
5138 }
5139
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005140 public void moveTaskToBack(int task) {
5141 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5142 "moveTaskToBack()");
5143
5144 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005145 if (mMainStack.mResumedActivity != null
5146 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005147 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5148 Binder.getCallingUid(), "Task to back")) {
5149 return;
5150 }
5151 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005152 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005153 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005154 Binder.restoreCallingIdentity(origId);
5155 }
5156 }
5157
5158 /**
5159 * Moves an activity, and all of the other activities within the same task, to the bottom
5160 * of the history stack. The activity's order within the task is unchanged.
5161 *
5162 * @param token A reference to the activity we wish to move
5163 * @param nonRoot If false then this only works if the activity is the root
5164 * of a task; if true it will work for any activity in a task.
5165 * @return Returns true if the move completed, false if not.
5166 */
5167 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
5168 synchronized(this) {
5169 final long origId = Binder.clearCallingIdentity();
5170 int taskId = getTaskForActivityLocked(token, !nonRoot);
5171 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005172 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005173 }
5174 Binder.restoreCallingIdentity(origId);
5175 }
5176 return false;
5177 }
5178
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005179 public void moveTaskBackwards(int task) {
5180 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5181 "moveTaskBackwards()");
5182
5183 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005184 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5185 Binder.getCallingUid(), "Task backwards")) {
5186 return;
5187 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005188 final long origId = Binder.clearCallingIdentity();
5189 moveTaskBackwardsLocked(task);
5190 Binder.restoreCallingIdentity(origId);
5191 }
5192 }
5193
5194 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005195 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005196 }
5197
5198 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
5199 synchronized(this) {
5200 return getTaskForActivityLocked(token, onlyRoot);
5201 }
5202 }
5203
5204 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005205 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005206 TaskRecord lastTask = null;
5207 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005208 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005209 if (r == token) {
5210 if (!onlyRoot || lastTask != r.task) {
5211 return r.task.taskId;
5212 }
5213 return -1;
5214 }
5215 lastTask = r.task;
5216 }
5217
5218 return -1;
5219 }
5220
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005221 public void finishOtherInstances(IBinder token, ComponentName className) {
5222 synchronized(this) {
5223 final long origId = Binder.clearCallingIdentity();
5224
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005225 int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005226 TaskRecord lastTask = null;
5227 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005228 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005229 if (r.realActivity.equals(className)
5230 && r != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005231 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005232 null, "others")) {
5233 i--;
5234 N--;
5235 }
5236 }
5237 lastTask = r.task;
5238 }
5239
5240 Binder.restoreCallingIdentity(origId);
5241 }
5242 }
5243
5244 // =========================================================
5245 // THUMBNAILS
5246 // =========================================================
5247
5248 public void reportThumbnail(IBinder token,
5249 Bitmap thumbnail, CharSequence description) {
5250 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
5251 final long origId = Binder.clearCallingIdentity();
5252 sendPendingThumbnail(null, token, thumbnail, description, true);
5253 Binder.restoreCallingIdentity(origId);
5254 }
5255
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005256 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005257 Bitmap thumbnail, CharSequence description, boolean always) {
5258 TaskRecord task = null;
5259 ArrayList receivers = null;
5260
5261 //System.out.println("Send pending thumbnail: " + r);
5262
5263 synchronized(this) {
5264 if (r == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005265 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005266 if (index < 0) {
5267 return;
5268 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005269 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005270 }
5271 if (thumbnail == null) {
5272 thumbnail = r.thumbnail;
5273 description = r.description;
5274 }
5275 if (thumbnail == null && !always) {
5276 // If there is no thumbnail, and this entry is not actually
5277 // going away, then abort for now and pick up the next
5278 // thumbnail we get.
5279 return;
5280 }
5281 task = r.task;
5282
5283 int N = mPendingThumbnails.size();
5284 int i=0;
5285 while (i<N) {
5286 PendingThumbnailsRecord pr =
5287 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
5288 //System.out.println("Looking in " + pr.pendingRecords);
5289 if (pr.pendingRecords.remove(r)) {
5290 if (receivers == null) {
5291 receivers = new ArrayList();
5292 }
5293 receivers.add(pr);
5294 if (pr.pendingRecords.size() == 0) {
5295 pr.finished = true;
5296 mPendingThumbnails.remove(i);
5297 N--;
5298 continue;
5299 }
5300 }
5301 i++;
5302 }
5303 }
5304
5305 if (receivers != null) {
5306 final int N = receivers.size();
5307 for (int i=0; i<N; i++) {
5308 try {
5309 PendingThumbnailsRecord pr =
5310 (PendingThumbnailsRecord)receivers.get(i);
5311 pr.receiver.newThumbnail(
5312 task != null ? task.taskId : -1, thumbnail, description);
5313 if (pr.finished) {
5314 pr.receiver.finished();
5315 }
5316 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005317 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005318 }
5319 }
5320 }
5321 }
5322
5323 // =========================================================
5324 // CONTENT PROVIDERS
5325 // =========================================================
5326
5327 private final List generateApplicationProvidersLocked(ProcessRecord app) {
5328 List providers = null;
5329 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005330 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005331 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005332 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005333 } catch (RemoteException ex) {
5334 }
5335 if (providers != null) {
5336 final int N = providers.size();
5337 for (int i=0; i<N; i++) {
5338 ProviderInfo cpi =
5339 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005340 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005341 if (cpr == null) {
5342 cpr = new ContentProviderRecord(cpi, app.info);
5343 mProvidersByClass.put(cpi.name, cpr);
5344 }
5345 app.pubProviders.put(cpi.name, cpr);
5346 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005347 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005348 }
5349 }
5350 return providers;
5351 }
5352
5353 private final String checkContentProviderPermissionLocked(
Dianne Hackbornb424b632010-08-18 15:59:05 -07005354 ProviderInfo cpi, ProcessRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005355 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
5356 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
5357 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005358 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005359 == PackageManager.PERMISSION_GRANTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005360 return null;
5361 }
5362 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005363 cpi.applicationInfo.uid, cpi.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005364 == PackageManager.PERMISSION_GRANTED) {
5365 return null;
5366 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005367
5368 PathPermission[] pps = cpi.pathPermissions;
5369 if (pps != null) {
5370 int i = pps.length;
5371 while (i > 0) {
5372 i--;
5373 PathPermission pp = pps[i];
5374 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005375 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005376 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005377 return null;
5378 }
5379 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005380 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005381 == PackageManager.PERMISSION_GRANTED) {
5382 return null;
5383 }
5384 }
5385 }
5386
Dianne Hackbornb424b632010-08-18 15:59:05 -07005387 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
5388 if (perms != null) {
5389 for (Map.Entry<Uri, UriPermission> uri : perms.entrySet()) {
5390 if (uri.getKey().getAuthority().equals(cpi.authority)) {
5391 return null;
5392 }
5393 }
5394 }
5395
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005396 String msg;
5397 if (!cpi.exported) {
5398 msg = "Permission Denial: opening provider " + cpi.name
5399 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5400 + ", uid=" + callingUid + ") that is not exported from uid "
5401 + cpi.applicationInfo.uid;
5402 } else {
5403 msg = "Permission Denial: opening provider " + cpi.name
5404 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5405 + ", uid=" + callingUid + ") requires "
5406 + cpi.readPermission + " or " + cpi.writePermission;
5407 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005408 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005409 return msg;
5410 }
5411
5412 private final ContentProviderHolder getContentProviderImpl(
5413 IApplicationThread caller, String name) {
5414 ContentProviderRecord cpr;
5415 ProviderInfo cpi = null;
5416
5417 synchronized(this) {
5418 ProcessRecord r = null;
5419 if (caller != null) {
5420 r = getRecordForAppLocked(caller);
5421 if (r == null) {
5422 throw new SecurityException(
5423 "Unable to find app for caller " + caller
5424 + " (pid=" + Binder.getCallingPid()
5425 + ") when getting content provider " + name);
5426 }
5427 }
5428
5429 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07005430 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005431 if (cpr != null) {
5432 cpi = cpr.info;
Dianne Hackbornb424b632010-08-18 15:59:05 -07005433 String msg;
5434 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5435 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005436 }
5437
5438 if (r != null && cpr.canRunHere(r)) {
5439 // This provider has been published or is in the process
5440 // of being published... but it is also allowed to run
5441 // in the caller's process, so don't make a connection
5442 // and just let the caller instantiate its own instance.
5443 if (cpr.provider != null) {
5444 // don't give caller the provider object, it needs
5445 // to make its own.
5446 cpr = new ContentProviderRecord(cpr);
5447 }
5448 return cpr;
5449 }
5450
5451 final long origId = Binder.clearCallingIdentity();
5452
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005453 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005454 // return it right away.
5455 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005456 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005457 "Adding provider requested by "
5458 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005459 + cpr.info.processName);
5460 Integer cnt = r.conProviders.get(cpr);
5461 if (cnt == null) {
5462 r.conProviders.put(cpr, new Integer(1));
5463 } else {
5464 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5465 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005466 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07005467 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
5468 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07005469 // make sure to count it as being accessed and thus
5470 // back up on the LRU list. This is good because
5471 // content providers are often expensive to start.
5472 updateLruProcessLocked(cpr.app, false, true);
5473 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07005474 } else {
5475 cpr.externals++;
5476 }
5477
5478 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005479 updateOomAdjLocked(cpr.app);
5480 }
5481
5482 Binder.restoreCallingIdentity(origId);
5483
5484 } else {
5485 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005486 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005487 resolveContentProvider(name,
5488 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005489 } catch (RemoteException ex) {
5490 }
5491 if (cpi == null) {
5492 return null;
5493 }
5494
Dianne Hackbornb424b632010-08-18 15:59:05 -07005495 String msg;
5496 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5497 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005498 }
5499
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07005500 if (!mProcessesReady && !mDidUpdate && !mWaitingUpdate
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005501 && !cpi.processName.equals("system")) {
5502 // If this content provider does not run in the system
5503 // process, and the system is not yet ready to run other
5504 // processes, then fail fast instead of hanging.
5505 throw new IllegalArgumentException(
5506 "Attempt to launch content provider before system ready");
5507 }
5508
Dianne Hackborn860755f2010-06-03 18:47:52 -07005509 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005510 final boolean firstClass = cpr == null;
5511 if (firstClass) {
5512 try {
5513 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005514 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005515 getApplicationInfo(
5516 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005517 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005518 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005519 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005520 + cpi.name);
5521 return null;
5522 }
5523 cpr = new ContentProviderRecord(cpi, ai);
5524 } catch (RemoteException ex) {
5525 // pm is in same process, this will never happen.
5526 }
5527 }
5528
5529 if (r != null && cpr.canRunHere(r)) {
5530 // If this is a multiprocess provider, then just return its
5531 // info and allow the caller to instantiate it. Only do
5532 // this if the provider is the same user as the caller's
5533 // process, or can run as root (so can be in any process).
5534 return cpr;
5535 }
5536
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005537 if (DEBUG_PROVIDER) {
5538 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08005539 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005540 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005541 }
5542
5543 // This is single process, and our app is now connecting to it.
5544 // See if we are already in the process of launching this
5545 // provider.
5546 final int N = mLaunchingProviders.size();
5547 int i;
5548 for (i=0; i<N; i++) {
5549 if (mLaunchingProviders.get(i) == cpr) {
5550 break;
5551 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005552 }
5553
5554 // If the provider is not already being launched, then get it
5555 // started.
5556 if (i >= N) {
5557 final long origId = Binder.clearCallingIdentity();
Dianne Hackborne7f97212011-02-24 14:40:20 -08005558
5559 try {
5560 // Content provider is now in use, its package can't be stopped.
5561 try {
5562 AppGlobals.getPackageManager().setPackageStoppedState(
5563 cpr.appInfo.packageName, false);
5564 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08005565 } catch (IllegalArgumentException e) {
5566 Slog.w(TAG, "Failed trying to unstop package "
5567 + cpr.appInfo.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08005568 }
5569
5570 ProcessRecord proc = startProcessLocked(cpi.processName,
5571 cpr.appInfo, false, 0, "content provider",
5572 new ComponentName(cpi.applicationInfo.packageName,
5573 cpi.name), false);
5574 if (proc == null) {
5575 Slog.w(TAG, "Unable to launch app "
5576 + cpi.applicationInfo.packageName + "/"
5577 + cpi.applicationInfo.uid + " for provider "
5578 + name + ": process is bad");
5579 return null;
5580 }
5581 cpr.launchingApp = proc;
5582 mLaunchingProviders.add(cpr);
5583 } finally {
5584 Binder.restoreCallingIdentity(origId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005585 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005586 }
5587
5588 // Make sure the provider is published (the same provider class
5589 // may be published under multiple names).
5590 if (firstClass) {
5591 mProvidersByClass.put(cpi.name, cpr);
5592 }
5593 mProvidersByName.put(name, cpr);
5594
5595 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005596 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005597 "Adding provider requested by "
5598 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005599 + cpr.info.processName);
5600 Integer cnt = r.conProviders.get(cpr);
5601 if (cnt == null) {
5602 r.conProviders.put(cpr, new Integer(1));
5603 } else {
5604 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5605 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005606 cpr.clients.add(r);
5607 } else {
5608 cpr.externals++;
5609 }
5610 }
5611 }
5612
5613 // Wait for the provider to be published...
5614 synchronized (cpr) {
5615 while (cpr.provider == null) {
5616 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005617 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005618 + cpi.applicationInfo.packageName + "/"
5619 + cpi.applicationInfo.uid + " for provider "
5620 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005621 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005622 cpi.applicationInfo.packageName,
5623 cpi.applicationInfo.uid, name);
5624 return null;
5625 }
5626 try {
5627 cpr.wait();
5628 } catch (InterruptedException ex) {
5629 }
5630 }
5631 }
5632 return cpr;
5633 }
5634
5635 public final ContentProviderHolder getContentProvider(
5636 IApplicationThread caller, String name) {
5637 if (caller == null) {
5638 String msg = "null IApplicationThread when getting content provider "
5639 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005640 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005641 throw new SecurityException(msg);
5642 }
5643
5644 return getContentProviderImpl(caller, name);
5645 }
5646
5647 private ContentProviderHolder getContentProviderExternal(String name) {
5648 return getContentProviderImpl(null, name);
5649 }
5650
5651 /**
5652 * Drop a content provider from a ProcessRecord's bookkeeping
5653 * @param cpr
5654 */
5655 public void removeContentProvider(IApplicationThread caller, String name) {
5656 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005657 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005658 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005659 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005660 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005661 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005662 return;
5663 }
5664 final ProcessRecord r = getRecordForAppLocked(caller);
5665 if (r == null) {
5666 throw new SecurityException(
5667 "Unable to find app for caller " + caller +
5668 " when removing content provider " + name);
5669 }
5670 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005671 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005672 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005673 + r.info.processName + " from process "
5674 + localCpr.appInfo.processName);
5675 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005676 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08005677 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005678 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005679 return;
5680 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005681 Integer cnt = r.conProviders.get(localCpr);
5682 if (cnt == null || cnt.intValue() <= 1) {
5683 localCpr.clients.remove(r);
5684 r.conProviders.remove(localCpr);
5685 } else {
5686 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
5687 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005688 }
5689 updateOomAdjLocked();
5690 }
5691 }
5692
5693 private void removeContentProviderExternal(String name) {
5694 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005695 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005696 if(cpr == null) {
5697 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005698 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005699 return;
5700 }
5701
5702 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005703 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005704 localCpr.externals--;
5705 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005706 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005707 }
5708 updateOomAdjLocked();
5709 }
5710 }
5711
5712 public final void publishContentProviders(IApplicationThread caller,
5713 List<ContentProviderHolder> providers) {
5714 if (providers == null) {
5715 return;
5716 }
5717
5718 synchronized(this) {
5719 final ProcessRecord r = getRecordForAppLocked(caller);
5720 if (r == null) {
5721 throw new SecurityException(
5722 "Unable to find app for caller " + caller
5723 + " (pid=" + Binder.getCallingPid()
5724 + ") when publishing content providers");
5725 }
5726
5727 final long origId = Binder.clearCallingIdentity();
5728
5729 final int N = providers.size();
5730 for (int i=0; i<N; i++) {
5731 ContentProviderHolder src = providers.get(i);
5732 if (src == null || src.info == null || src.provider == null) {
5733 continue;
5734 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005735 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005736 if (dst != null) {
5737 mProvidersByClass.put(dst.info.name, dst);
5738 String names[] = dst.info.authority.split(";");
5739 for (int j = 0; j < names.length; j++) {
5740 mProvidersByName.put(names[j], dst);
5741 }
5742
5743 int NL = mLaunchingProviders.size();
5744 int j;
5745 for (j=0; j<NL; j++) {
5746 if (mLaunchingProviders.get(j) == dst) {
5747 mLaunchingProviders.remove(j);
5748 j--;
5749 NL--;
5750 }
5751 }
5752 synchronized (dst) {
5753 dst.provider = src.provider;
5754 dst.app = r;
5755 dst.notifyAll();
5756 }
5757 updateOomAdjLocked(r);
5758 }
5759 }
5760
5761 Binder.restoreCallingIdentity(origId);
5762 }
5763 }
5764
5765 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005766 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06005767 synchronized (mSelf) {
5768 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
5769 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005770 if (providers != null) {
5771 for (int i=providers.size()-1; i>=0; i--) {
5772 ProviderInfo pi = (ProviderInfo)providers.get(i);
5773 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5774 Slog.w(TAG, "Not installing system proc provider " + pi.name
5775 + ": not system .apk");
5776 providers.remove(i);
5777 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005778 }
5779 }
5780 }
Josh Bartel2ecce342010-02-25 10:55:48 -06005781 if (providers != null) {
5782 mSystemThread.installSystemProviders(providers);
5783 }
Svetoslav Ganov54d068e2011-03-02 12:58:40 -08005784
5785 mSelf.mCoreSettingsObserver = new CoreSettingsObserver(mSelf);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005786 }
5787
Dianne Hackborncca1f0e2010-09-26 18:34:53 -07005788 /**
5789 * Allows app to retrieve the MIME type of a URI without having permission
5790 * to access its content provider.
5791 *
5792 * CTS tests for this functionality can be run with "runtest cts-appsecurity".
5793 *
5794 * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
5795 * src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
5796 */
5797 public String getProviderMimeType(Uri uri) {
5798 final String name = uri.getAuthority();
5799 final long ident = Binder.clearCallingIdentity();
5800 ContentProviderHolder holder = null;
5801
5802 try {
5803 holder = getContentProviderExternal(name);
5804 if (holder != null) {
5805 return holder.provider.getType(uri);
5806 }
5807 } catch (RemoteException e) {
5808 Log.w(TAG, "Content provider dead retrieving " + uri, e);
5809 return null;
5810 } finally {
5811 if (holder != null) {
5812 removeContentProviderExternal(name);
5813 }
5814 Binder.restoreCallingIdentity(ident);
5815 }
5816
5817 return null;
5818 }
5819
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005820 // =========================================================
5821 // GLOBAL MANAGEMENT
5822 // =========================================================
5823
5824 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
5825 ApplicationInfo info, String customProcess) {
5826 String proc = customProcess != null ? customProcess : info.processName;
5827 BatteryStatsImpl.Uid.Proc ps = null;
5828 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5829 synchronized (stats) {
5830 ps = stats.getProcessStatsLocked(info.uid, proc);
5831 }
5832 return new ProcessRecord(ps, thread, info, proc);
5833 }
5834
5835 final ProcessRecord addAppLocked(ApplicationInfo info) {
5836 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
5837
5838 if (app == null) {
5839 app = newProcessRecordLocked(null, info, null);
5840 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005841 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005842 }
5843
Dianne Hackborne7f97212011-02-24 14:40:20 -08005844 // This package really, really can not be stopped.
5845 try {
5846 AppGlobals.getPackageManager().setPackageStoppedState(
5847 info.packageName, false);
5848 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08005849 } catch (IllegalArgumentException e) {
5850 Slog.w(TAG, "Failed trying to unstop package "
5851 + info.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08005852 }
5853
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005854 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
5855 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
5856 app.persistent = true;
5857 app.maxAdj = CORE_SERVER_ADJ;
5858 }
5859 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
5860 mPersistentStartingProcesses.add(app);
5861 startProcessLocked(app, "added application", app.processName);
5862 }
5863
5864 return app;
5865 }
5866
5867 public void unhandledBack() {
5868 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
5869 "unhandledBack()");
5870
5871 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005872 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08005873 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005874 TAG, "Performing unhandledBack(): stack size = " + count);
5875 if (count > 1) {
5876 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005877 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005878 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
5879 Binder.restoreCallingIdentity(origId);
5880 }
5881 }
5882 }
5883
5884 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
5885 String name = uri.getAuthority();
5886 ContentProviderHolder cph = getContentProviderExternal(name);
5887 ParcelFileDescriptor pfd = null;
5888 if (cph != null) {
5889 // We record the binder invoker's uid in thread-local storage before
5890 // going to the content provider to open the file. Later, in the code
5891 // that handles all permissions checks, we look for this uid and use
5892 // that rather than the Activity Manager's own uid. The effect is that
5893 // we do the check against the caller's permissions even though it looks
5894 // to the content provider like the Activity Manager itself is making
5895 // the request.
5896 sCallerIdentity.set(new Identity(
5897 Binder.getCallingPid(), Binder.getCallingUid()));
5898 try {
5899 pfd = cph.provider.openFile(uri, "r");
5900 } catch (FileNotFoundException e) {
5901 // do nothing; pfd will be returned null
5902 } finally {
5903 // Ensure that whatever happens, we clean up the identity state
5904 sCallerIdentity.remove();
5905 }
5906
5907 // We've got the fd now, so we're done with the provider.
5908 removeContentProviderExternal(name);
5909 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005910 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005911 }
5912 return pfd;
5913 }
5914
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005915 // Actually is sleeping or shutting down or whatever else in the future
5916 // is an inactive state.
5917 public boolean isSleeping() {
5918 return mSleeping || mShuttingDown;
5919 }
5920
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005921 public void goingToSleep() {
5922 synchronized(this) {
5923 mSleeping = true;
5924 mWindowManager.setEventDispatching(false);
5925
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005926 mMainStack.stopIfSleepingLocked();
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005927
5928 // Initialize the wake times of all processes.
Dianne Hackborn287952c2010-09-22 22:34:31 -07005929 checkExcessivePowerUsageLocked(false);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005930 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
5931 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07005932 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005933 }
5934 }
5935
Dianne Hackborn55280a92009-05-07 15:53:46 -07005936 public boolean shutdown(int timeout) {
5937 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
5938 != PackageManager.PERMISSION_GRANTED) {
5939 throw new SecurityException("Requires permission "
5940 + android.Manifest.permission.SHUTDOWN);
5941 }
5942
5943 boolean timedout = false;
5944
5945 synchronized(this) {
5946 mShuttingDown = true;
5947 mWindowManager.setEventDispatching(false);
5948
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005949 if (mMainStack.mResumedActivity != null) {
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005950 mMainStack.stopIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07005951 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005952 while (mMainStack.mResumedActivity != null
5953 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07005954 long delay = endTime - System.currentTimeMillis();
5955 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005956 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07005957 timedout = true;
5958 break;
5959 }
5960 try {
5961 this.wait();
5962 } catch (InterruptedException e) {
5963 }
5964 }
5965 }
5966 }
5967
5968 mUsageStatsService.shutdown();
5969 mBatteryStatsService.shutdown();
5970
5971 return timedout;
5972 }
5973
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005974 public final void activitySlept(IBinder token) {
5975 if (localLOGV) Slog.v(
5976 TAG, "Activity slept: token=" + token);
5977
5978 ActivityRecord r = null;
5979
5980 final long origId = Binder.clearCallingIdentity();
5981
5982 synchronized (this) {
5983 int index = mMainStack.indexOfTokenLocked(token);
5984 if (index >= 0) {
5985 r = (ActivityRecord)mMainStack.mHistory.get(index);
5986 mMainStack.activitySleptLocked(r);
5987 }
5988 }
5989
5990 Binder.restoreCallingIdentity(origId);
5991 }
5992
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005993 public void wakingUp() {
5994 synchronized(this) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005995 mWindowManager.setEventDispatching(true);
5996 mSleeping = false;
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005997 mMainStack.awakeFromSleepingLocked();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005998 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005999 }
6000 }
6001
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006002 public void stopAppSwitches() {
6003 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
6004 != PackageManager.PERMISSION_GRANTED) {
6005 throw new SecurityException("Requires permission "
6006 + android.Manifest.permission.STOP_APP_SWITCHES);
6007 }
6008
6009 synchronized(this) {
6010 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
6011 + APP_SWITCH_DELAY_TIME;
6012 mDidAppSwitch = false;
6013 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
6014 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
6015 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
6016 }
6017 }
6018
6019 public void resumeAppSwitches() {
6020 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
6021 != PackageManager.PERMISSION_GRANTED) {
6022 throw new SecurityException("Requires permission "
6023 + android.Manifest.permission.STOP_APP_SWITCHES);
6024 }
6025
6026 synchronized(this) {
6027 // Note that we don't execute any pending app switches... we will
6028 // let those wait until either the timeout, or the next start
6029 // activity request.
6030 mAppSwitchesAllowedTime = 0;
6031 }
6032 }
6033
6034 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
6035 String name) {
6036 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
6037 return true;
6038 }
6039
6040 final int perm = checkComponentPermission(
6041 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08006042 callingUid, -1, true);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006043 if (perm == PackageManager.PERMISSION_GRANTED) {
6044 return true;
6045 }
6046
Joe Onorato8a9b2202010-02-26 18:56:32 -08006047 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006048 return false;
6049 }
6050
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006051 public void setDebugApp(String packageName, boolean waitForDebugger,
6052 boolean persistent) {
6053 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
6054 "setDebugApp()");
6055
6056 // Note that this is not really thread safe if there are multiple
6057 // callers into it at the same time, but that's not a situation we
6058 // care about.
6059 if (persistent) {
6060 final ContentResolver resolver = mContext.getContentResolver();
6061 Settings.System.putString(
6062 resolver, Settings.System.DEBUG_APP,
6063 packageName);
6064 Settings.System.putInt(
6065 resolver, Settings.System.WAIT_FOR_DEBUGGER,
6066 waitForDebugger ? 1 : 0);
6067 }
6068
6069 synchronized (this) {
6070 if (!persistent) {
6071 mOrigDebugApp = mDebugApp;
6072 mOrigWaitForDebugger = mWaitForDebugger;
6073 }
6074 mDebugApp = packageName;
6075 mWaitForDebugger = waitForDebugger;
6076 mDebugTransient = !persistent;
6077 if (packageName != null) {
6078 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006079 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006080 Binder.restoreCallingIdentity(origId);
6081 }
6082 }
6083 }
6084
6085 public void setAlwaysFinish(boolean enabled) {
6086 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
6087 "setAlwaysFinish()");
6088
6089 Settings.System.putInt(
6090 mContext.getContentResolver(),
6091 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
6092
6093 synchronized (this) {
6094 mAlwaysFinishActivities = enabled;
6095 }
6096 }
6097
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006098 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006099 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006100 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006101 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006102 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006103 }
6104 }
6105
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08006106 public boolean isUserAMonkey() {
6107 // For now the fact that there is a controller implies
6108 // we have a monkey.
6109 synchronized (this) {
6110 return mController != null;
6111 }
6112 }
6113
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006114 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06006115 synchronized (this) {
6116 mWatchers.register(watcher);
6117 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006118 }
6119
6120 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06006121 synchronized (this) {
6122 mWatchers.unregister(watcher);
6123 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006124 }
6125
Daniel Sandler69a48172010-06-23 16:29:36 -04006126 public void setImmersive(IBinder token, boolean immersive) {
6127 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006128 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04006129 if (index < 0) {
6130 throw new IllegalArgumentException();
6131 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006132 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04006133 r.immersive = immersive;
6134 }
6135 }
6136
6137 public boolean isImmersive(IBinder token) {
6138 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006139 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04006140 if (index < 0) {
6141 throw new IllegalArgumentException();
6142 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006143 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04006144 return r.immersive;
6145 }
6146 }
6147
6148 public boolean isTopActivityImmersive() {
6149 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006150 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Daniel Sandler69a48172010-06-23 16:29:36 -04006151 return (r != null) ? r.immersive : false;
6152 }
6153 }
6154
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006155 public final void enterSafeMode() {
6156 synchronized(this) {
6157 // It only makes sense to do this before the system is ready
6158 // and started launching other packages.
6159 if (!mSystemReady) {
6160 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006161 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006162 } catch (RemoteException e) {
6163 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006164 }
6165 }
6166 }
6167
Jeff Brownb09abc12011-01-13 21:08:27 -08006168 public final void showSafeModeOverlay() {
6169 View v = LayoutInflater.from(mContext).inflate(
6170 com.android.internal.R.layout.safe_mode, null);
6171 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
6172 lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
6173 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
6174 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
6175 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
6176 lp.format = v.getBackground().getOpacity();
6177 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
6178 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
6179 ((WindowManager)mContext.getSystemService(
6180 Context.WINDOW_SERVICE)).addView(v, lp);
6181 }
6182
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006183 public void noteWakeupAlarm(IIntentSender sender) {
6184 if (!(sender instanceof PendingIntentRecord)) {
6185 return;
6186 }
6187 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
6188 synchronized (stats) {
6189 if (mBatteryStatsService.isOnBattery()) {
6190 mBatteryStatsService.enforceCallingPermission();
6191 PendingIntentRecord rec = (PendingIntentRecord)sender;
6192 int MY_UID = Binder.getCallingUid();
6193 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
6194 BatteryStatsImpl.Uid.Pkg pkg =
6195 stats.getPackageStatsLocked(uid, rec.key.packageName);
6196 pkg.incWakeupsLocked();
6197 }
6198 }
6199 }
6200
Dianne Hackborn64825172011-03-02 21:32:58 -08006201 public boolean killPids(int[] pids, String pReason, boolean secure) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006202 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006203 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006204 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006205 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006206 // XXX Note: don't acquire main activity lock here, because the window
6207 // manager calls in with its locks held.
6208
6209 boolean killed = false;
6210 synchronized (mPidsSelfLocked) {
6211 int[] types = new int[pids.length];
6212 int worstType = 0;
6213 for (int i=0; i<pids.length; i++) {
6214 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6215 if (proc != null) {
6216 int type = proc.setAdj;
6217 types[i] = type;
6218 if (type > worstType) {
6219 worstType = type;
6220 }
6221 }
6222 }
6223
Dianne Hackborn64825172011-03-02 21:32:58 -08006224 // If the worst oom_adj is somewhere in the hidden proc LRU range,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006225 // then constrain it so we will kill all hidden procs.
6226 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
6227 worstType = HIDDEN_APP_MIN_ADJ;
6228 }
Dianne Hackborn64825172011-03-02 21:32:58 -08006229
6230 // If this is not a secure call, don't let it kill processes that
6231 // are important.
6232 if (!secure && worstType < SECONDARY_SERVER_ADJ) {
6233 worstType = SECONDARY_SERVER_ADJ;
6234 }
6235
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006236 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006237 for (int i=0; i<pids.length; i++) {
6238 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6239 if (proc == null) {
6240 continue;
6241 }
6242 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006243 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07006244 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006245 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
6246 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006247 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006248 proc.killedBackground = true;
6249 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006250 }
6251 }
6252 }
6253 return killed;
6254 }
6255
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006256 public final void startRunning(String pkg, String cls, String action,
6257 String data) {
6258 synchronized(this) {
6259 if (mStartRunning) {
6260 return;
6261 }
6262 mStartRunning = true;
6263 mTopComponent = pkg != null && cls != null
6264 ? new ComponentName(pkg, cls) : null;
6265 mTopAction = action != null ? action : Intent.ACTION_MAIN;
6266 mTopData = data;
6267 if (!mSystemReady) {
6268 return;
6269 }
6270 }
6271
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006272 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006273 }
6274
6275 private void retrieveSettings() {
6276 final ContentResolver resolver = mContext.getContentResolver();
6277 String debugApp = Settings.System.getString(
6278 resolver, Settings.System.DEBUG_APP);
6279 boolean waitForDebugger = Settings.System.getInt(
6280 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
6281 boolean alwaysFinishActivities = Settings.System.getInt(
6282 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
6283
6284 Configuration configuration = new Configuration();
6285 Settings.System.getConfiguration(resolver, configuration);
6286
6287 synchronized (this) {
6288 mDebugApp = mOrigDebugApp = debugApp;
6289 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
6290 mAlwaysFinishActivities = alwaysFinishActivities;
6291 // This happens before any activities are started, so we can
6292 // change mConfiguration in-place.
6293 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08006294 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006295 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006296 }
6297 }
6298
6299 public boolean testIsSystemReady() {
6300 // no need to synchronize(this) just to read & return the value
6301 return mSystemReady;
6302 }
6303
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006304 private static File getCalledPreBootReceiversFile() {
6305 File dataDir = Environment.getDataDirectory();
6306 File systemDir = new File(dataDir, "system");
6307 File fname = new File(systemDir, "called_pre_boots.dat");
6308 return fname;
6309 }
6310
6311 private static ArrayList<ComponentName> readLastDonePreBootReceivers() {
6312 ArrayList<ComponentName> lastDoneReceivers = new ArrayList<ComponentName>();
6313 File file = getCalledPreBootReceiversFile();
6314 FileInputStream fis = null;
6315 try {
6316 fis = new FileInputStream(file);
6317 DataInputStream dis = new DataInputStream(new BufferedInputStream(fis, 2048));
6318 int vers = dis.readInt();
6319 String codename = dis.readUTF();
6320 if (vers == android.os.Build.VERSION.SDK_INT
6321 && codename.equals(android.os.Build.VERSION.CODENAME)) {
6322 int num = dis.readInt();
6323 while (num > 0) {
6324 num--;
6325 String pkg = dis.readUTF();
6326 String cls = dis.readUTF();
6327 lastDoneReceivers.add(new ComponentName(pkg, cls));
6328 }
6329 }
6330 } catch (FileNotFoundException e) {
6331 } catch (IOException e) {
6332 Slog.w(TAG, "Failure reading last done pre-boot receivers", e);
6333 } finally {
6334 if (fis != null) {
6335 try {
6336 fis.close();
6337 } catch (IOException e) {
6338 }
6339 }
6340 }
6341 return lastDoneReceivers;
6342 }
6343
6344 private static void writeLastDonePreBootReceivers(ArrayList<ComponentName> list) {
6345 File file = getCalledPreBootReceiversFile();
6346 FileOutputStream fos = null;
6347 DataOutputStream dos = null;
6348 try {
6349 Slog.i(TAG, "Writing new set of last done pre-boot receivers...");
6350 fos = new FileOutputStream(file);
6351 dos = new DataOutputStream(new BufferedOutputStream(fos, 2048));
6352 dos.writeInt(android.os.Build.VERSION.SDK_INT);
6353 dos.writeUTF(android.os.Build.VERSION.CODENAME);
6354 dos.writeInt(list.size());
6355 for (int i=0; i<list.size(); i++) {
6356 dos.writeUTF(list.get(i).getPackageName());
6357 dos.writeUTF(list.get(i).getClassName());
6358 }
6359 } catch (IOException e) {
6360 Slog.w(TAG, "Failure writing last done pre-boot receivers", e);
6361 file.delete();
6362 } finally {
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07006363 FileUtils.sync(fos);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006364 if (dos != null) {
6365 try {
6366 dos.close();
6367 } catch (IOException e) {
6368 // TODO Auto-generated catch block
6369 e.printStackTrace();
6370 }
6371 }
6372 }
6373 }
6374
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006375 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006376 // In the simulator, startRunning will never have been called, which
6377 // normally sets a few crucial variables. Do it here instead.
6378 if (!Process.supportsProcesses()) {
6379 mStartRunning = true;
6380 mTopAction = Intent.ACTION_MAIN;
6381 }
6382
6383 synchronized(this) {
6384 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006385 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006386 return;
6387 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006388
6389 // Check to see if there are any update receivers to run.
6390 if (!mDidUpdate) {
6391 if (mWaitingUpdate) {
6392 return;
6393 }
6394 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
6395 List<ResolveInfo> ris = null;
6396 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006397 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006398 intent, null, 0);
6399 } catch (RemoteException e) {
6400 }
6401 if (ris != null) {
6402 for (int i=ris.size()-1; i>=0; i--) {
6403 if ((ris.get(i).activityInfo.applicationInfo.flags
6404 &ApplicationInfo.FLAG_SYSTEM) == 0) {
6405 ris.remove(i);
6406 }
6407 }
6408 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006409
6410 ArrayList<ComponentName> lastDoneReceivers = readLastDonePreBootReceivers();
6411
6412 final ArrayList<ComponentName> doneReceivers = new ArrayList<ComponentName>();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006413 for (int i=0; i<ris.size(); i++) {
6414 ActivityInfo ai = ris.get(i).activityInfo;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006415 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6416 if (lastDoneReceivers.contains(comp)) {
6417 ris.remove(i);
6418 i--;
6419 }
6420 }
6421
6422 for (int i=0; i<ris.size(); i++) {
6423 ActivityInfo ai = ris.get(i).activityInfo;
6424 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6425 doneReceivers.add(comp);
6426 intent.setComponent(comp);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006427 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08006428 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006429 finisher = new IIntentReceiver.Stub() {
6430 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07006431 String data, Bundle extras, boolean ordered,
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006432 boolean sticky) {
6433 // The raw IIntentReceiver interface is called
6434 // with the AM lock held, so redispatch to
6435 // execute our code without the lock.
6436 mHandler.post(new Runnable() {
6437 public void run() {
6438 synchronized (ActivityManagerService.this) {
6439 mDidUpdate = true;
6440 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006441 writeLastDonePreBootReceivers(doneReceivers);
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006442 systemReady(goingCallback);
6443 }
6444 });
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006445 }
6446 };
6447 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006448 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006449 broadcastIntentLocked(null, null, intent, null, finisher,
6450 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08006451 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006452 mWaitingUpdate = true;
6453 }
6454 }
6455 }
6456 if (mWaitingUpdate) {
6457 return;
6458 }
6459 mDidUpdate = true;
6460 }
6461
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006462 mSystemReady = true;
6463 if (!mStartRunning) {
6464 return;
6465 }
6466 }
6467
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006468 ArrayList<ProcessRecord> procsToKill = null;
6469 synchronized(mPidsSelfLocked) {
6470 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
6471 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
6472 if (!isAllowedWhileBooting(proc.info)){
6473 if (procsToKill == null) {
6474 procsToKill = new ArrayList<ProcessRecord>();
6475 }
6476 procsToKill.add(proc);
6477 }
6478 }
6479 }
6480
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006481 synchronized(this) {
6482 if (procsToKill != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006483 for (int i=procsToKill.size()-1; i>=0; i--) {
6484 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08006485 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006486 removeProcessLocked(proc, true);
6487 }
6488 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006489
6490 // Now that we have cleaned up any update processes, we
6491 // are ready to start launching real processes and know that
6492 // we won't trample on them any more.
6493 mProcessesReady = true;
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006494 }
6495
Joe Onorato8a9b2202010-02-26 18:56:32 -08006496 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006497 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006498 SystemClock.uptimeMillis());
6499
6500 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006501 // Make sure we have no pre-ready processes sitting around.
6502
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006503 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
6504 ResolveInfo ri = mContext.getPackageManager()
6505 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07006506 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006507 CharSequence errorMsg = null;
6508 if (ri != null) {
6509 ActivityInfo ai = ri.activityInfo;
6510 ApplicationInfo app = ai.applicationInfo;
6511 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
6512 mTopAction = Intent.ACTION_FACTORY_TEST;
6513 mTopData = null;
6514 mTopComponent = new ComponentName(app.packageName,
6515 ai.name);
6516 } else {
6517 errorMsg = mContext.getResources().getText(
6518 com.android.internal.R.string.factorytest_not_system);
6519 }
6520 } else {
6521 errorMsg = mContext.getResources().getText(
6522 com.android.internal.R.string.factorytest_no_action);
6523 }
6524 if (errorMsg != null) {
6525 mTopAction = null;
6526 mTopData = null;
6527 mTopComponent = null;
6528 Message msg = Message.obtain();
6529 msg.what = SHOW_FACTORY_ERROR_MSG;
6530 msg.getData().putCharSequence("msg", errorMsg);
6531 mHandler.sendMessage(msg);
6532 }
6533 }
6534 }
6535
6536 retrieveSettings();
6537
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006538 if (goingCallback != null) goingCallback.run();
6539
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006540 synchronized (this) {
6541 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
6542 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006543 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07006544 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006545 if (apps != null) {
6546 int N = apps.size();
6547 int i;
6548 for (i=0; i<N; i++) {
6549 ApplicationInfo info
6550 = (ApplicationInfo)apps.get(i);
6551 if (info != null &&
6552 !info.packageName.equals("android")) {
6553 addAppLocked(info);
6554 }
6555 }
6556 }
6557 } catch (RemoteException ex) {
6558 // pm is in same process, this will never happen.
6559 }
6560 }
6561
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006562 // Start up initial activity.
6563 mBooting = true;
6564
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006565 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006566 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006567 Message msg = Message.obtain();
6568 msg.what = SHOW_UID_ERROR_MSG;
6569 mHandler.sendMessage(msg);
6570 }
6571 } catch (RemoteException e) {
6572 }
6573
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006574 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006575 }
6576 }
6577
Dan Egnorb7f03672009-12-09 16:22:32 -08006578 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006579 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006580 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006581 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006582 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006583 startAppProblemLocked(app);
6584 app.stopFreezingAllLocked();
6585 return handleAppCrashLocked(app);
6586 }
6587
Dan Egnorb7f03672009-12-09 16:22:32 -08006588 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006589 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006590 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006591 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006592 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
6593 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006594 startAppProblemLocked(app);
6595 app.stopFreezingAllLocked();
6596 }
6597
6598 /**
6599 * Generate a process error record, suitable for attachment to a ProcessRecord.
6600 *
6601 * @param app The ProcessRecord in which the error occurred.
6602 * @param condition Crashing, Application Not Responding, etc. Values are defined in
6603 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08006604 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006605 * @param shortMsg Short message describing the crash.
6606 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08006607 * @param stackTrace Full crash stack trace, may be null.
6608 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006609 * @return Returns a fully-formed AppErrorStateInfo record.
6610 */
6611 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006612 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006613 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08006614
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006615 report.condition = condition;
6616 report.processName = app.processName;
6617 report.pid = app.pid;
6618 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08006619 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006620 report.shortMsg = shortMsg;
6621 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08006622 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006623
6624 return report;
6625 }
6626
Dan Egnor42471dd2010-01-07 17:25:22 -08006627 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006628 synchronized (this) {
6629 app.crashing = false;
6630 app.crashingReport = null;
6631 app.notResponding = false;
6632 app.notRespondingReport = null;
6633 if (app.anrDialog == fromDialog) {
6634 app.anrDialog = null;
6635 }
6636 if (app.waitDialog == fromDialog) {
6637 app.waitDialog = null;
6638 }
6639 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08006640 handleAppCrashLocked(app);
Dianne Hackborn8633e682010-04-22 16:03:41 -07006641 Slog.i(ActivityManagerService.TAG, "Killing "
6642 + app.processName + " (pid=" + app.pid + "): user's request");
6643 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
6644 app.processName, app.setAdj, "user's request after error");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006645 Process.killProcess(app.pid);
6646 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006647 }
6648 }
Dan Egnor42471dd2010-01-07 17:25:22 -08006649
Dan Egnorb7f03672009-12-09 16:22:32 -08006650 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006651 long now = SystemClock.uptimeMillis();
6652
6653 Long crashTime = mProcessCrashTimes.get(app.info.processName,
6654 app.info.uid);
6655 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
6656 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006657 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006658 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006659 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006660 app.info.processName, app.info.uid);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006661 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
6662 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006663 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006664 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006665 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006666 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006667 }
6668 }
6669 if (!app.persistent) {
Dianne Hackborn070783f2010-12-29 16:46:28 -08006670 // Don't let services in this process be restarted and potentially
6671 // annoy the user repeatedly. Unless it is persistent, since those
6672 // processes run critical code.
6673 killServicesLocked(app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006674 // We don't want to start this process again until the user
6675 // explicitly does so... but for persistent process, we really
6676 // need to keep it running. If a persistent process is actually
6677 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08006678 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006679 app.info.processName);
6680 mBadProcesses.put(app.info.processName, app.info.uid, now);
6681 app.bad = true;
6682 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
6683 app.removed = true;
6684 removeProcessLocked(app, false);
6685 return false;
6686 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006687 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006688 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006689 if (r.app == app) {
6690 // If the top running activity is from this crashing
6691 // process, then terminate it to avoid getting in a loop.
6692 Slog.w(TAG, " Force finishing activity "
6693 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006694 int index = mMainStack.indexOfTokenLocked(r);
6695 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006696 Activity.RESULT_CANCELED, null, "crashed");
Dianne Hackborn070783f2010-12-29 16:46:28 -08006697 // Also terminate any activities below it that aren't yet
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006698 // stopped, to avoid a situation where one will get
6699 // re-start our crashing activity once it gets resumed again.
6700 index--;
6701 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006702 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006703 if (r.state == ActivityState.RESUMED
6704 || r.state == ActivityState.PAUSING
6705 || r.state == ActivityState.PAUSED) {
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -08006706 if (!r.isHomeActivity || mHomeProcess != r.app) {
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006707 Slog.w(TAG, " Force finishing activity "
6708 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006709 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006710 Activity.RESULT_CANCELED, null, "crashed");
6711 }
6712 }
6713 }
6714 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006715 }
6716
6717 // Bump up the crash count of any services currently running in the proc.
6718 if (app.services.size() != 0) {
6719 // Any services running in the application need to be placed
6720 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07006721 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006722 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006723 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006724 sr.crashCount++;
6725 }
6726 }
Mattias Larssona4fd0072010-06-22 22:37:03 +02006727
6728 // If the crashing process is what we consider to be the "home process" and it has been
6729 // replaced by a third-party app, clear the package preferred activities from packages
6730 // with a home activity running in the process to prevent a repeatedly crashing app
6731 // from blocking the user to manually clear the list.
6732 if (app == mHomeProcess && mHomeProcess.activities.size() > 0
6733 && (mHomeProcess.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
6734 Iterator it = mHomeProcess.activities.iterator();
6735 while (it.hasNext()) {
Jean-Baptiste Queru5ea89f72010-07-30 09:30:31 -07006736 ActivityRecord r = (ActivityRecord)it.next();
Mattias Larssona4fd0072010-06-22 22:37:03 +02006737 if (r.isHomeActivity) {
6738 Log.i(TAG, "Clearing package preferred activities from " + r.packageName);
6739 try {
6740 ActivityThread.getPackageManager()
6741 .clearPackagePreferredActivities(r.packageName);
6742 } catch (RemoteException c) {
6743 // pm is in same process, this will never happen.
6744 }
6745 }
6746 }
6747 }
6748
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006749 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
6750 return true;
6751 }
6752
6753 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006754 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
6755 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006756 skipCurrentReceiverLocked(app);
6757 }
6758
6759 void skipCurrentReceiverLocked(ProcessRecord app) {
6760 boolean reschedule = false;
6761 BroadcastRecord r = app.curReceiver;
6762 if (r != null) {
6763 // The current broadcast is waiting for this app's receiver
6764 // to be finished. Looks like that's not going to happen, so
6765 // let the broadcast continue.
Jeff Brown4d94a762010-09-23 11:33:28 -07006766 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006767 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6768 r.resultExtras, r.resultAbort, true);
6769 reschedule = true;
6770 }
6771 r = mPendingBroadcast;
6772 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006773 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006774 "skip & discard pending app " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -07006775 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006776 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6777 r.resultExtras, r.resultAbort, true);
6778 reschedule = true;
6779 }
6780 if (reschedule) {
6781 scheduleBroadcastsLocked();
6782 }
6783 }
6784
Dan Egnor60d87622009-12-16 16:32:58 -08006785 /**
6786 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
6787 * The application process will exit immediately after this call returns.
6788 * @param app object of the crashing app, null for the system server
6789 * @param crashInfo describing the exception
6790 */
6791 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
6792 ProcessRecord r = findAppProcess(app);
6793
6794 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
6795 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006796 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006797 crashInfo.exceptionClassName,
6798 crashInfo.exceptionMessage,
6799 crashInfo.throwFileName,
6800 crashInfo.throwLineNumber);
6801
Dan Egnor42471dd2010-01-07 17:25:22 -08006802 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006803
6804 crashApplication(r, crashInfo);
6805 }
6806
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006807 public void handleApplicationStrictModeViolation(
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006808 IBinder app,
6809 int violationMask,
6810 StrictMode.ViolationInfo info) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006811 ProcessRecord r = findAppProcess(app);
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006812
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006813 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -08006814 Integer stackFingerprint = info.hashCode();
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006815 boolean logIt = true;
6816 synchronized (mAlreadyLoggedViolatedStacks) {
6817 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
6818 logIt = false;
6819 // TODO: sub-sample into EventLog for these, with
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006820 // the info.durationMillis? Then we'd get
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006821 // the relative pain numbers, without logging all
6822 // the stack traces repeatedly. We'd want to do
6823 // likewise in the client code, which also does
6824 // dup suppression, before the Binder call.
6825 } else {
6826 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
6827 mAlreadyLoggedViolatedStacks.clear();
6828 }
6829 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
6830 }
6831 }
6832 if (logIt) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006833 logStrictModeViolationToDropBox(r, info);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006834 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006835 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006836
6837 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
6838 AppErrorResult result = new AppErrorResult();
6839 synchronized (this) {
6840 final long origId = Binder.clearCallingIdentity();
6841
6842 Message msg = Message.obtain();
6843 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
6844 HashMap<String, Object> data = new HashMap<String, Object>();
6845 data.put("result", result);
6846 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006847 data.put("violationMask", violationMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006848 data.put("info", info);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006849 msg.obj = data;
6850 mHandler.sendMessage(msg);
6851
6852 Binder.restoreCallingIdentity(origId);
6853 }
6854 int res = result.get();
Dianne Hackbornb424b632010-08-18 15:59:05 -07006855 Slog.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006856 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006857 }
6858
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006859 // Depending on the policy in effect, there could be a bunch of
6860 // these in quick succession so we try to batch these together to
6861 // minimize disk writes, number of dropbox entries, and maximize
6862 // compression, by having more fewer, larger records.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006863 private void logStrictModeViolationToDropBox(
6864 ProcessRecord process,
6865 StrictMode.ViolationInfo info) {
6866 if (info == null) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006867 return;
6868 }
6869 final boolean isSystemApp = process == null ||
6870 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
6871 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
6872 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
6873 final DropBoxManager dbox = (DropBoxManager)
6874 mContext.getSystemService(Context.DROPBOX_SERVICE);
6875
6876 // Exit early if the dropbox isn't configured to accept this report type.
6877 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6878
6879 boolean bufferWasEmpty;
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006880 boolean needsFlush;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006881 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
6882 synchronized (sb) {
6883 bufferWasEmpty = sb.length() == 0;
6884 appendDropBoxProcessHeaders(process, sb);
6885 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6886 sb.append("System-App: ").append(isSystemApp).append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006887 sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
6888 if (info.violationNumThisLoop != 0) {
6889 sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
6890 }
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07006891 if (info.numAnimationsRunning != 0) {
6892 sb.append("Animations-Running: ").append(info.numAnimationsRunning).append("\n");
6893 }
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07006894 if (info.broadcastIntentAction != null) {
6895 sb.append("Broadcast-Intent-Action: ").append(info.broadcastIntentAction).append("\n");
6896 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08006897 if (info.durationMillis != -1) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006898 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006899 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08006900 if (info.numInstances != -1) {
6901 sb.append("Instance-Count: ").append(info.numInstances).append("\n");
6902 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08006903 if (info.tags != null) {
6904 for (String tag : info.tags) {
6905 sb.append("Span-Tag: ").append(tag).append("\n");
6906 }
6907 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006908 sb.append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006909 if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
6910 sb.append(info.crashInfo.stackTrace);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006911 }
6912 sb.append("\n");
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006913
6914 // Only buffer up to ~64k. Various logging bits truncate
6915 // things at 128k.
6916 needsFlush = (sb.length() > 64 * 1024);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006917 }
6918
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006919 // Flush immediately if the buffer's grown too large, or this
6920 // is a non-system app. Non-system apps are isolated with a
6921 // different tag & policy and not batched.
6922 //
6923 // Batching is useful during internal testing with
6924 // StrictMode settings turned up high. Without batching,
6925 // thousands of separate files could be created on boot.
6926 if (!isSystemApp || needsFlush) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006927 new Thread("Error dump: " + dropboxTag) {
6928 @Override
6929 public void run() {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006930 String report;
6931 synchronized (sb) {
6932 report = sb.toString();
6933 sb.delete(0, sb.length());
6934 sb.trimToSize();
6935 }
6936 if (report.length() != 0) {
6937 dbox.addText(dropboxTag, report);
6938 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006939 }
6940 }.start();
6941 return;
6942 }
6943
6944 // System app batching:
6945 if (!bufferWasEmpty) {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006946 // An existing dropbox-writing thread is outstanding, so
6947 // we don't need to start it up. The existing thread will
6948 // catch the buffer appends we just did.
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006949 return;
6950 }
6951
6952 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
6953 // (After this point, we shouldn't access AMS internal data structures.)
6954 new Thread("Error dump: " + dropboxTag) {
6955 @Override
6956 public void run() {
6957 // 5 second sleep to let stacks arrive and be batched together
6958 try {
6959 Thread.sleep(5000); // 5 seconds
6960 } catch (InterruptedException e) {}
6961
6962 String errorReport;
6963 synchronized (mStrictModeBuffer) {
6964 errorReport = mStrictModeBuffer.toString();
6965 if (errorReport.length() == 0) {
6966 return;
6967 }
6968 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
6969 mStrictModeBuffer.trimToSize();
6970 }
6971 dbox.addText(dropboxTag, errorReport);
6972 }
6973 }.start();
6974 }
6975
Dan Egnor60d87622009-12-16 16:32:58 -08006976 /**
6977 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
6978 * @param app object of the crashing app, null for the system server
6979 * @param tag reported by the caller
6980 * @param crashInfo describing the context of the error
6981 * @return true if the process should exit immediately (WTF is fatal)
6982 */
6983 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08006984 ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnor60d87622009-12-16 16:32:58 -08006985 ProcessRecord r = findAppProcess(app);
6986
6987 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
6988 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006989 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006990 tag, crashInfo.exceptionMessage);
6991
Dan Egnor42471dd2010-01-07 17:25:22 -08006992 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006993
Doug Zongker43866e02010-01-07 12:09:54 -08006994 if (Settings.Secure.getInt(mContext.getContentResolver(),
6995 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08006996 crashApplication(r, crashInfo);
6997 return true;
6998 } else {
6999 return false;
7000 }
7001 }
7002
7003 /**
7004 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
7005 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
7006 */
7007 private ProcessRecord findAppProcess(IBinder app) {
7008 if (app == null) {
7009 return null;
7010 }
7011
7012 synchronized (this) {
7013 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
7014 final int NA = apps.size();
7015 for (int ia=0; ia<NA; ia++) {
7016 ProcessRecord p = apps.valueAt(ia);
7017 if (p.thread != null && p.thread.asBinder() == app) {
7018 return p;
7019 }
7020 }
7021 }
7022
Joe Onorato8a9b2202010-02-26 18:56:32 -08007023 Slog.w(TAG, "Can't find mystery application: " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08007024 return null;
7025 }
7026 }
7027
7028 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007029 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
7030 * to append various headers to the dropbox log text.
Dan Egnor60d87622009-12-16 16:32:58 -08007031 */
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07007032 private void appendDropBoxProcessHeaders(ProcessRecord process, StringBuilder sb) {
7033 // Note: ProcessRecord 'process' is guarded by the service
7034 // instance. (notably process.pkgList, which could otherwise change
7035 // concurrently during execution of this method)
7036 synchronized (this) {
7037 if (process == null || process.pid == MY_PID) {
7038 sb.append("Process: system_server\n");
7039 } else {
7040 sb.append("Process: ").append(process.processName).append("\n");
7041 }
7042 if (process == null) {
7043 return;
7044 }
Dan Egnora455d192010-03-12 08:52:28 -08007045 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007046 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08007047 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
7048 for (String pkg : process.pkgList) {
7049 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08007050 try {
Dan Egnora455d192010-03-12 08:52:28 -08007051 PackageInfo pi = pm.getPackageInfo(pkg, 0);
7052 if (pi != null) {
7053 sb.append(" v").append(pi.versionCode);
7054 if (pi.versionName != null) {
7055 sb.append(" (").append(pi.versionName).append(")");
7056 }
7057 }
7058 } catch (RemoteException e) {
7059 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08007060 }
Dan Egnora455d192010-03-12 08:52:28 -08007061 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08007062 }
Dan Egnora455d192010-03-12 08:52:28 -08007063 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007064 }
7065
7066 private static String processClass(ProcessRecord process) {
7067 if (process == null || process.pid == MY_PID) {
7068 return "system_server";
7069 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
7070 return "system_app";
7071 } else {
7072 return "data_app";
7073 }
7074 }
7075
7076 /**
7077 * Write a description of an error (crash, WTF, ANR) to the drop box.
7078 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
7079 * @param process which caused the error, null means the system server
7080 * @param activity which triggered the error, null if unknown
7081 * @param parent activity related to the error, null if unknown
7082 * @param subject line related to the error, null if absent
7083 * @param report in long form describing the error, null if absent
7084 * @param logFile to include in the report, null if none
7085 * @param crashInfo giving an application stack trace, null if absent
7086 */
7087 public void addErrorToDropBox(String eventType,
7088 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
7089 final String report, final File logFile,
7090 final ApplicationErrorReport.CrashInfo crashInfo) {
7091 // NOTE -- this must never acquire the ActivityManagerService lock,
7092 // otherwise the watchdog may be prevented from resetting the system.
7093
7094 final String dropboxTag = processClass(process) + "_" + eventType;
7095 final DropBoxManager dbox = (DropBoxManager)
7096 mContext.getSystemService(Context.DROPBOX_SERVICE);
7097
7098 // Exit early if the dropbox isn't configured to accept this report type.
7099 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
7100
7101 final StringBuilder sb = new StringBuilder(1024);
7102 appendDropBoxProcessHeaders(process, sb);
Dan Egnora455d192010-03-12 08:52:28 -08007103 if (activity != null) {
7104 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
7105 }
7106 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
7107 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
7108 }
7109 if (parent != null && parent != activity) {
7110 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
7111 }
7112 if (subject != null) {
7113 sb.append("Subject: ").append(subject).append("\n");
7114 }
7115 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
Christian Lindeberg03d2ca62010-09-28 14:52:20 +02007116 if (Debug.isDebuggerConnected()) {
7117 sb.append("Debugger: Connected\n");
7118 }
Dan Egnora455d192010-03-12 08:52:28 -08007119 sb.append("\n");
7120
7121 // Do the rest in a worker thread to avoid blocking the caller on I/O
7122 // (After this point, we shouldn't access AMS internal data structures.)
7123 Thread worker = new Thread("Error dump: " + dropboxTag) {
7124 @Override
7125 public void run() {
7126 if (report != null) {
7127 sb.append(report);
7128 }
7129 if (logFile != null) {
7130 try {
7131 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
7132 } catch (IOException e) {
7133 Slog.e(TAG, "Error reading " + logFile, e);
7134 }
7135 }
7136 if (crashInfo != null && crashInfo.stackTrace != null) {
7137 sb.append(crashInfo.stackTrace);
7138 }
7139
7140 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
7141 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
7142 if (lines > 0) {
7143 sb.append("\n");
7144
7145 // Merge several logcat streams, and take the last N lines
7146 InputStreamReader input = null;
7147 try {
7148 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
7149 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
7150 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
7151
7152 try { logcat.getOutputStream().close(); } catch (IOException e) {}
7153 try { logcat.getErrorStream().close(); } catch (IOException e) {}
7154 input = new InputStreamReader(logcat.getInputStream());
7155
7156 int num;
7157 char[] buf = new char[8192];
7158 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
7159 } catch (IOException e) {
7160 Slog.e(TAG, "Error running logcat", e);
7161 } finally {
7162 if (input != null) try { input.close(); } catch (IOException e) {}
7163 }
7164 }
7165
7166 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08007167 }
Dan Egnora455d192010-03-12 08:52:28 -08007168 };
7169
7170 if (process == null || process.pid == MY_PID) {
7171 worker.run(); // We may be about to die -- need to run this synchronously
7172 } else {
7173 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08007174 }
7175 }
7176
7177 /**
7178 * Bring up the "unexpected error" dialog box for a crashing app.
7179 * Deal with edge cases (intercepts from instrumented applications,
7180 * ActivityController, error intent receivers, that sort of thing).
7181 * @param r the application crashing
7182 * @param crashInfo describing the failure
7183 */
7184 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007185 long timeMillis = System.currentTimeMillis();
7186 String shortMsg = crashInfo.exceptionClassName;
7187 String longMsg = crashInfo.exceptionMessage;
7188 String stackTrace = crashInfo.stackTrace;
7189 if (shortMsg != null && longMsg != null) {
7190 longMsg = shortMsg + ": " + longMsg;
7191 } else if (shortMsg != null) {
7192 longMsg = shortMsg;
7193 }
7194
Dan Egnor60d87622009-12-16 16:32:58 -08007195 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007196 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007197 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007198 try {
7199 String name = r != null ? r.processName : null;
7200 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08007201 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08007202 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007203 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007204 + " at watcher's request");
7205 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08007206 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007207 }
7208 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007209 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007210 }
7211 }
7212
7213 final long origId = Binder.clearCallingIdentity();
7214
7215 // If this process is running instrumentation, finish it.
7216 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007217 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007218 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08007219 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
7220 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007221 Bundle info = new Bundle();
7222 info.putString("shortMsg", shortMsg);
7223 info.putString("longMsg", longMsg);
7224 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
7225 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007226 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007227 }
7228
Dan Egnor60d87622009-12-16 16:32:58 -08007229 // If we can't identify the process or it's already exceeded its crash quota,
7230 // quit right away without showing a crash dialog.
7231 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007232 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007233 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007234 }
7235
7236 Message msg = Message.obtain();
7237 msg.what = SHOW_ERROR_MSG;
7238 HashMap data = new HashMap();
7239 data.put("result", result);
7240 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007241 msg.obj = data;
7242 mHandler.sendMessage(msg);
7243
7244 Binder.restoreCallingIdentity(origId);
7245 }
7246
7247 int res = result.get();
7248
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007249 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007250 synchronized (this) {
7251 if (r != null) {
7252 mProcessCrashTimes.put(r.info.processName, r.info.uid,
7253 SystemClock.uptimeMillis());
7254 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007255 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007256 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007257 }
7258 }
7259
7260 if (appErrorIntent != null) {
7261 try {
7262 mContext.startActivity(appErrorIntent);
7263 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007264 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007265 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007266 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007267 }
Dan Egnorb7f03672009-12-09 16:22:32 -08007268
7269 Intent createAppErrorIntentLocked(ProcessRecord r,
7270 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
7271 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007272 if (report == null) {
7273 return null;
7274 }
7275 Intent result = new Intent(Intent.ACTION_APP_ERROR);
7276 result.setComponent(r.errorReportReceiver);
7277 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
7278 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
7279 return result;
7280 }
7281
Dan Egnorb7f03672009-12-09 16:22:32 -08007282 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
7283 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007284 if (r.errorReportReceiver == null) {
7285 return null;
7286 }
7287
7288 if (!r.crashing && !r.notResponding) {
7289 return null;
7290 }
7291
Dan Egnorb7f03672009-12-09 16:22:32 -08007292 ApplicationErrorReport report = new ApplicationErrorReport();
7293 report.packageName = r.info.packageName;
7294 report.installerPackageName = r.errorReportReceiver.getPackageName();
7295 report.processName = r.processName;
7296 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01007297 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007298
Dan Egnorb7f03672009-12-09 16:22:32 -08007299 if (r.crashing) {
7300 report.type = ApplicationErrorReport.TYPE_CRASH;
7301 report.crashInfo = crashInfo;
7302 } else if (r.notResponding) {
7303 report.type = ApplicationErrorReport.TYPE_ANR;
7304 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007305
Dan Egnorb7f03672009-12-09 16:22:32 -08007306 report.anrInfo.activity = r.notRespondingReport.tag;
7307 report.anrInfo.cause = r.notRespondingReport.shortMsg;
7308 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007309 }
7310
Dan Egnorb7f03672009-12-09 16:22:32 -08007311 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007312 }
7313
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007314 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
7315 // assume our apps are happy - lazy create the list
7316 List<ActivityManager.ProcessErrorStateInfo> errList = null;
7317
7318 synchronized (this) {
7319
7320 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007321 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7322 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007323 if ((app.thread != null) && (app.crashing || app.notResponding)) {
7324 // This one's in trouble, so we'll generate a report for it
7325 // crashes are higher priority (in case there's a crash *and* an anr)
7326 ActivityManager.ProcessErrorStateInfo report = null;
7327 if (app.crashing) {
7328 report = app.crashingReport;
7329 } else if (app.notResponding) {
7330 report = app.notRespondingReport;
7331 }
7332
7333 if (report != null) {
7334 if (errList == null) {
7335 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
7336 }
7337 errList.add(report);
7338 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007339 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007340 " crashing = " + app.crashing +
7341 " notResponding = " + app.notResponding);
7342 }
7343 }
7344 }
7345 }
7346
7347 return errList;
7348 }
7349
7350 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
7351 // Lazy instantiation of list
7352 List<ActivityManager.RunningAppProcessInfo> runList = null;
7353 synchronized (this) {
7354 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007355 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7356 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007357 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
7358 // Generate process state info for running application
7359 ActivityManager.RunningAppProcessInfo currApp =
7360 new ActivityManager.RunningAppProcessInfo(app.processName,
7361 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07007362 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007363 if (mHeavyWeightProcess == app) {
Dianne Hackborn482566e2010-09-03 12:51:28 -07007364 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007365 }
Dianne Hackborn42499172010-10-15 18:45:07 -07007366 if (app.persistent) {
7367 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_PERSISTENT;
7368 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007369 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007370 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007371 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
7372 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
7373 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08007374 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
7375 } else if (adj >= HOME_APP_ADJ) {
7376 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
7377 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007378 } else if (adj >= SECONDARY_SERVER_ADJ) {
7379 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007380 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackborn5383f502010-10-22 12:59:20 -07007381 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007382 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
7383 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007384 } else if (adj >= VISIBLE_APP_ADJ) {
7385 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
7386 } else {
7387 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
7388 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007389 currApp.importanceReasonCode = app.adjTypeCode;
7390 if (app.adjSource instanceof ProcessRecord) {
7391 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007392 } else if (app.adjSource instanceof ActivityRecord) {
7393 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007394 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
7395 }
7396 if (app.adjTarget instanceof ComponentName) {
7397 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
7398 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007399 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007400 // + " lru=" + currApp.lru);
7401 if (runList == null) {
7402 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
7403 }
7404 runList.add(currApp);
7405 }
7406 }
7407 }
7408 return runList;
7409 }
7410
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007411 public List<ApplicationInfo> getRunningExternalApplications() {
7412 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
7413 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
7414 if (runningApps != null && runningApps.size() > 0) {
7415 Set<String> extList = new HashSet<String>();
7416 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
7417 if (app.pkgList != null) {
7418 for (String pkg : app.pkgList) {
7419 extList.add(pkg);
7420 }
7421 }
7422 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007423 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007424 for (String pkg : extList) {
7425 try {
7426 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
7427 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
7428 retList.add(info);
7429 }
7430 } catch (RemoteException e) {
7431 }
7432 }
7433 }
7434 return retList;
7435 }
7436
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007437 @Override
7438 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007439 if (checkCallingPermission(android.Manifest.permission.DUMP)
7440 != PackageManager.PERMISSION_GRANTED) {
7441 pw.println("Permission Denial: can't dump ActivityManager from from pid="
7442 + Binder.getCallingPid()
7443 + ", uid=" + Binder.getCallingUid()
7444 + " without permission "
7445 + android.Manifest.permission.DUMP);
7446 return;
7447 }
7448
7449 boolean dumpAll = false;
7450
7451 int opti = 0;
7452 while (opti < args.length) {
7453 String opt = args[opti];
7454 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
7455 break;
7456 }
7457 opti++;
7458 if ("-a".equals(opt)) {
7459 dumpAll = true;
7460 } else if ("-h".equals(opt)) {
7461 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007462 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007463 pw.println(" cmd may be one of:");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007464 pw.println(" a[ctivities]: activity stack state");
7465 pw.println(" b[roadcasts]: broadcast state");
7466 pw.println(" i[ntents]: pending intent state");
7467 pw.println(" p[rocesses]: process state");
7468 pw.println(" o[om]: out of memory management");
7469 pw.println(" prov[iders]: content provider state");
7470 pw.println(" s[ervices]: service state");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007471 pw.println(" service [name]: service client-side state");
Dianne Hackborn30d71892010-12-11 10:37:55 -08007472 pw.println(" cmd may also be a component name (com.foo/.myApp),");
7473 pw.println(" a partial substring in a component name, or an");
7474 pw.println(" ActivityRecord hex object identifier.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007475 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007476 } else {
7477 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007478 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007479 }
7480
7481 // Is the caller requesting to dump a particular piece of data?
7482 if (opti < args.length) {
7483 String cmd = args[opti];
7484 opti++;
7485 if ("activities".equals(cmd) || "a".equals(cmd)) {
7486 synchronized (this) {
7487 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007488 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007489 return;
7490 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
7491 synchronized (this) {
7492 dumpBroadcastsLocked(fd, pw, args, opti, true);
7493 }
7494 return;
7495 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
7496 synchronized (this) {
7497 dumpPendingIntentsLocked(fd, pw, args, opti, true);
7498 }
7499 return;
7500 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
7501 synchronized (this) {
7502 dumpProcessesLocked(fd, pw, args, opti, true);
7503 }
7504 return;
Dianne Hackborn287952c2010-09-22 22:34:31 -07007505 } else if ("oom".equals(cmd) || "o".equals(cmd)) {
7506 synchronized (this) {
7507 dumpOomLocked(fd, pw, args, opti, true);
7508 }
7509 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007510 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
7511 synchronized (this) {
7512 dumpProvidersLocked(fd, pw, args, opti, true);
7513 }
7514 return;
7515 } else if ("service".equals(cmd)) {
Joe Onoratoeb95b082010-10-21 14:54:19 -04007516 dumpService(fd, pw, args, opti);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007517 return;
7518 } else if ("services".equals(cmd) || "s".equals(cmd)) {
7519 synchronized (this) {
7520 dumpServicesLocked(fd, pw, args, opti, true);
7521 }
7522 return;
Dianne Hackborn625ac272010-09-17 18:29:22 -07007523 } else {
7524 // Dumping a single activity?
7525 if (dumpActivity(fd, pw, cmd, args, opti, dumpAll)) {
7526 return;
7527 }
Dianne Hackborn30d71892010-12-11 10:37:55 -08007528 pw.println("Bad activity command, or no activities match: " + cmd);
7529 pw.println("Use -h for help.");
7530 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007531 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007532 }
7533
7534 // No piece of data specified, dump everything.
7535 synchronized (this) {
7536 boolean needSep;
7537 if (dumpAll) {
7538 pw.println("Providers in Current Activity Manager State:");
7539 }
7540 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
7541 if (needSep) {
7542 pw.println(" ");
7543 }
7544 if (dumpAll) {
7545 pw.println("-------------------------------------------------------------------------------");
7546 pw.println("Broadcasts in Current Activity Manager State:");
7547 }
7548 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
7549 if (needSep) {
7550 pw.println(" ");
7551 }
7552 if (dumpAll) {
7553 pw.println("-------------------------------------------------------------------------------");
7554 pw.println("Services in Current Activity Manager State:");
7555 }
7556 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
7557 if (needSep) {
7558 pw.println(" ");
7559 }
7560 if (dumpAll) {
7561 pw.println("-------------------------------------------------------------------------------");
7562 pw.println("PendingIntents in Current Activity Manager State:");
7563 }
7564 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
7565 if (needSep) {
7566 pw.println(" ");
7567 }
7568 if (dumpAll) {
7569 pw.println("-------------------------------------------------------------------------------");
7570 pw.println("Activities in Current Activity Manager State:");
7571 }
7572 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
7573 if (needSep) {
7574 pw.println(" ");
7575 }
7576 if (dumpAll) {
7577 pw.println("-------------------------------------------------------------------------------");
7578 pw.println("Processes in Current Activity Manager State:");
7579 }
7580 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
7581 }
7582 }
7583
7584 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7585 int opti, boolean dumpAll, boolean needHeader) {
7586 if (needHeader) {
7587 pw.println(" Activity stack:");
7588 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007589 dumpHistoryList(pw, mMainStack.mHistory, " ", "Hist", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007590 pw.println(" ");
7591 pw.println(" Running activities (most recent first):");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007592 dumpHistoryList(pw, mMainStack.mLRUActivities, " ", "Run", false);
7593 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007594 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007595 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007596 dumpHistoryList(pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007597 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007598 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007599 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007600 pw.println(" Activities waiting to stop:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007601 dumpHistoryList(pw, mMainStack.mStoppingActivities, " ", "Stop", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007602 }
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08007603 if (mMainStack.mGoingToSleepActivities.size() > 0) {
7604 pw.println(" ");
7605 pw.println(" Activities waiting to sleep:");
7606 dumpHistoryList(pw, mMainStack.mGoingToSleepActivities, " ", "Sleep", false);
7607 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007608 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007609 pw.println(" ");
7610 pw.println(" Activities waiting to finish:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007611 dumpHistoryList(pw, mMainStack.mFinishingActivities, " ", "Fin", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007612 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007613
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007614 pw.println(" ");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007615 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
7616 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007617 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007618 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08007619 pw.println(" mSleepTimeout: " + mMainStack.mSleepTimeout);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007620
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007621 if (dumpAll && mRecentTasks.size() > 0) {
7622 pw.println(" ");
7623 pw.println("Recent tasks in Current Activity Manager State:");
7624
7625 final int N = mRecentTasks.size();
7626 for (int i=0; i<N; i++) {
7627 TaskRecord tr = mRecentTasks.get(i);
7628 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
7629 pw.println(tr);
7630 mRecentTasks.get(i).dump(pw, " ");
7631 }
7632 }
7633
7634 pw.println(" ");
7635 pw.println(" mCurTask: " + mCurTask);
7636
7637 return true;
7638 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07007639
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007640 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7641 int opti, boolean dumpAll) {
7642 boolean needSep = false;
7643 int numPers = 0;
7644
7645 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007646 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
7647 final int NA = procs.size();
7648 for (int ia=0; ia<NA; ia++) {
7649 if (!needSep) {
7650 pw.println(" All known processes:");
7651 needSep = true;
7652 }
7653 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007654 pw.print(r.persistent ? " *PERS*" : " *APP*");
7655 pw.print(" UID "); pw.print(procs.keyAt(ia));
7656 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007657 r.dump(pw, " ");
7658 if (r.persistent) {
7659 numPers++;
7660 }
7661 }
7662 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007663 }
7664
7665 if (mLruProcesses.size() > 0) {
7666 if (needSep) pw.println(" ");
7667 needSep = true;
7668 pw.println(" Running processes (most recent first):");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007669 dumpProcessOomList(pw, this, mLruProcesses, " ",
7670 "Proc", "PERS", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007671 needSep = true;
7672 }
7673
7674 synchronized (mPidsSelfLocked) {
7675 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007676 if (needSep) pw.println(" ");
7677 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007678 pw.println(" PID mappings:");
7679 for (int i=0; i<mPidsSelfLocked.size(); i++) {
7680 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
7681 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007682 }
7683 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007684 }
7685
7686 if (mForegroundProcesses.size() > 0) {
7687 if (needSep) pw.println(" ");
7688 needSep = true;
7689 pw.println(" Foreground Processes:");
7690 for (int i=0; i<mForegroundProcesses.size(); i++) {
7691 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
7692 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007693 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007694 }
7695
7696 if (mPersistentStartingProcesses.size() > 0) {
7697 if (needSep) pw.println(" ");
7698 needSep = true;
7699 pw.println(" Persisent processes that are starting:");
7700 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007701 "Starting Norm", "Restarting PERS");
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 (mStartingProcesses.size() > 0) {
7705 if (needSep) pw.println(" ");
7706 needSep = true;
7707 pw.println(" Processes that are starting:");
7708 dumpProcessList(pw, this, mStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007709 "Starting Norm", "Starting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007710 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007711
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007712 if (mRemovedProcesses.size() > 0) {
7713 if (needSep) pw.println(" ");
7714 needSep = true;
7715 pw.println(" Processes that are being removed:");
7716 dumpProcessList(pw, this, mRemovedProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007717 "Removed Norm", "Removed PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007718 }
7719
7720 if (mProcessesOnHold.size() > 0) {
7721 if (needSep) pw.println(" ");
7722 needSep = true;
7723 pw.println(" Processes that are on old until the system is ready:");
7724 dumpProcessList(pw, this, mProcessesOnHold, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007725 "OnHold Norm", "OnHold PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007726 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007727
Dianne Hackborn287952c2010-09-22 22:34:31 -07007728 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007729
7730 if (mProcessCrashTimes.getMap().size() > 0) {
7731 if (needSep) pw.println(" ");
7732 needSep = true;
7733 pw.println(" Time since processes crashed:");
7734 long now = SystemClock.uptimeMillis();
7735 for (Map.Entry<String, SparseArray<Long>> procs
7736 : mProcessCrashTimes.getMap().entrySet()) {
7737 SparseArray<Long> uids = procs.getValue();
7738 final int N = uids.size();
7739 for (int i=0; i<N; i++) {
7740 pw.print(" Process "); pw.print(procs.getKey());
7741 pw.print(" uid "); pw.print(uids.keyAt(i));
7742 pw.print(": last crashed ");
7743 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007744 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007745 }
7746 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007747 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007748
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007749 if (mBadProcesses.getMap().size() > 0) {
7750 if (needSep) pw.println(" ");
7751 needSep = true;
7752 pw.println(" Bad processes:");
7753 for (Map.Entry<String, SparseArray<Long>> procs
7754 : mBadProcesses.getMap().entrySet()) {
7755 SparseArray<Long> uids = procs.getValue();
7756 final int N = uids.size();
7757 for (int i=0; i<N; i++) {
7758 pw.print(" Bad process "); pw.print(procs.getKey());
7759 pw.print(" uid "); pw.print(uids.keyAt(i));
7760 pw.print(": crashed at time ");
7761 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007762 }
7763 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007764 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007765
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007766 pw.println(" ");
7767 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007768 if (mHeavyWeightProcess != null) {
7769 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7770 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007771 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007772 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007773 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
7774 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
7775 || mOrigWaitForDebugger) {
7776 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
7777 + " mDebugTransient=" + mDebugTransient
7778 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
7779 }
7780 if (mAlwaysFinishActivities || mController != null) {
7781 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
7782 + " mController=" + mController);
7783 }
7784 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007785 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007786 pw.println(" mStartRunning=" + mStartRunning
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07007787 + " mProcessesReady=" + mProcessesReady
7788 + " mSystemReady=" + mSystemReady);
7789 pw.println(" mBooting=" + mBooting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007790 + " mBooted=" + mBooted
7791 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn287952c2010-09-22 22:34:31 -07007792 pw.print(" mLastPowerCheckRealtime=");
7793 TimeUtils.formatDuration(mLastPowerCheckRealtime, pw);
7794 pw.println("");
7795 pw.print(" mLastPowerCheckUptime=");
7796 TimeUtils.formatDuration(mLastPowerCheckUptime, pw);
7797 pw.println("");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007798 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
7799 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07007800 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007801 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007802
7803 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007804 }
7805
Dianne Hackborn287952c2010-09-22 22:34:31 -07007806 boolean dumpProcessesToGc(FileDescriptor fd, PrintWriter pw, String[] args,
7807 int opti, boolean needSep, boolean dumpAll) {
7808 if (mProcessesToGc.size() > 0) {
7809 if (needSep) pw.println(" ");
7810 needSep = true;
7811 pw.println(" Processes that are waiting to GC:");
7812 long now = SystemClock.uptimeMillis();
7813 for (int i=0; i<mProcessesToGc.size(); i++) {
7814 ProcessRecord proc = mProcessesToGc.get(i);
7815 pw.print(" Process "); pw.println(proc);
7816 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
7817 pw.print(", last gced=");
7818 pw.print(now-proc.lastRequestedGc);
7819 pw.print(" ms ago, last lowMem=");
7820 pw.print(now-proc.lastLowMemory);
7821 pw.println(" ms ago");
7822
7823 }
7824 }
7825 return needSep;
7826 }
7827
7828 boolean dumpOomLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7829 int opti, boolean dumpAll) {
7830 boolean needSep = false;
7831
7832 if (mLruProcesses.size() > 0) {
7833 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>(mLruProcesses);
7834
7835 Comparator<ProcessRecord> comparator = new Comparator<ProcessRecord>() {
7836 @Override
7837 public int compare(ProcessRecord object1, ProcessRecord object2) {
7838 if (object1.setAdj != object2.setAdj) {
7839 return object1.setAdj > object2.setAdj ? -1 : 1;
7840 }
7841 if (object1.setSchedGroup != object2.setSchedGroup) {
7842 return object1.setSchedGroup > object2.setSchedGroup ? -1 : 1;
7843 }
7844 if (object1.keeping != object2.keeping) {
7845 return object1.keeping ? -1 : 1;
7846 }
7847 if (object1.pid != object2.pid) {
7848 return object1.pid > object2.pid ? -1 : 1;
7849 }
7850 return 0;
7851 }
7852 };
7853
7854 Collections.sort(procs, comparator);
7855
7856 if (needSep) pw.println(" ");
7857 needSep = true;
7858 pw.println(" Process OOM control:");
7859 dumpProcessOomList(pw, this, procs, " ",
7860 "Proc", "PERS", true);
7861 needSep = true;
7862 }
7863
7864 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
7865
7866 pw.println(" ");
7867 pw.println(" mHomeProcess: " + mHomeProcess);
7868 if (mHeavyWeightProcess != null) {
7869 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7870 }
7871
7872 return true;
7873 }
7874
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007875 /**
7876 * There are three ways to call this:
7877 * - no service specified: dump all the services
7878 * - a flattened component name that matched an existing service was specified as the
7879 * first arg: dump that one service
7880 * - the first arg isn't the flattened component name of an existing service:
7881 * dump all services whose component contains the first arg as a substring
7882 */
Joe Onoratoeb95b082010-10-21 14:54:19 -04007883 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args, int opti) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007884 String[] newArgs;
7885 String componentNameString;
7886 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08007887 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007888 componentNameString = null;
7889 newArgs = EMPTY_STRING_ARRAY;
7890 r = null;
7891 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007892 componentNameString = args[opti];
7893 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007894 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007895 synchronized (this) {
7896 r = componentName != null ? mServices.get(componentName) : null;
7897 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007898 newArgs = new String[args.length - opti];
7899 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007900 }
7901
7902 if (r != null) {
Joe Onoratoeb95b082010-10-21 14:54:19 -04007903 dumpService(fd, pw, r, newArgs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007904 } else {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007905 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
7906 synchronized (this) {
7907 for (ServiceRecord r1 : mServices.values()) {
7908 if (componentNameString == null
7909 || r1.name.flattenToString().contains(componentNameString)) {
7910 services.add(r1);
7911 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007912 }
7913 }
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007914 for (int i=0; i<services.size(); i++) {
Joe Onoratoeb95b082010-10-21 14:54:19 -04007915 dumpService(fd, pw, services.get(i), newArgs);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007916 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007917 }
7918 }
7919
7920 /**
7921 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
7922 * there is a thread associated with the service.
7923 */
Joe Onoratoeb95b082010-10-21 14:54:19 -04007924 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args) {
7925 pw.println("------------------------------------------------------------"
7926 + "-------------------");
7927 pw.println("APP SERVICE: " + r.name.flattenToString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007928 if (r.app != null && r.app.thread != null) {
7929 try {
7930 // flush anything that is already in the PrintWriter since the thread is going
7931 // to write to the file descriptor directly
7932 pw.flush();
7933 r.app.thread.dumpService(fd, r, args);
7934 pw.print("\n");
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007935 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007936 } catch (RemoteException e) {
7937 pw.println("got a RemoteException while dumping the service");
7938 }
7939 }
7940 }
7941
Dianne Hackborn625ac272010-09-17 18:29:22 -07007942 /**
7943 * There are three things that cmd can be:
7944 * - a flattened component name that matched an existing activity
7945 * - the cmd arg isn't the flattened component name of an existing activity:
7946 * dump all activity whose component contains the cmd as a substring
7947 * - A hex number of the ActivityRecord object instance.
7948 */
7949 protected boolean dumpActivity(FileDescriptor fd, PrintWriter pw, String name, String[] args,
7950 int opti, boolean dumpAll) {
7951 String[] newArgs;
7952 ComponentName componentName = ComponentName.unflattenFromString(name);
7953 int objectId = 0;
Dianne Hackborn30d71892010-12-11 10:37:55 -08007954 if (componentName == null) {
7955 // Not a '/' separated full component name; maybe an object ID?
7956 try {
7957 objectId = Integer.parseInt(name, 16);
7958 name = null;
7959 componentName = null;
7960 } catch (RuntimeException e) {
7961 }
Dianne Hackborn625ac272010-09-17 18:29:22 -07007962 }
7963 newArgs = new String[args.length - opti];
7964 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
7965
7966 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
7967 synchronized (this) {
7968 for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
7969 if (componentName != null) {
7970 if (r1.intent.getComponent().equals(componentName)) {
7971 activities.add(r1);
7972 }
7973 } else if (name != null) {
7974 if (r1.intent.getComponent().flattenToString().contains(name)) {
7975 activities.add(r1);
7976 }
Dianne Hackborn30d71892010-12-11 10:37:55 -08007977 } else if (System.identityHashCode(r1) == objectId) {
Dianne Hackborn625ac272010-09-17 18:29:22 -07007978 activities.add(r1);
7979 }
7980 }
7981 }
7982
7983 if (activities.size() <= 0) {
7984 return false;
7985 }
7986
Dianne Hackborn30d71892010-12-11 10:37:55 -08007987 TaskRecord lastTask = null;
7988 for (int i=activities.size()-1; i>=0; i--) {
7989 ActivityRecord r = (ActivityRecord)activities.get(i);
7990 if (lastTask != r.task) {
7991 lastTask = r.task;
7992 pw.print("* Task "); pw.print(lastTask.affinity);
7993 pw.print(" id="); pw.println(lastTask.taskId);
7994 if (dumpAll) {
7995 lastTask.dump(pw, " ");
7996 }
7997 }
7998 dumpActivity(" ", fd, pw, activities.get(i), newArgs, dumpAll);
Dianne Hackborn625ac272010-09-17 18:29:22 -07007999 }
8000 return true;
8001 }
8002
8003 /**
8004 * Invokes IApplicationThread.dumpActivity() on the thread of the specified activity if
8005 * there is a thread associated with the activity.
8006 */
Dianne Hackborn30d71892010-12-11 10:37:55 -08008007 private void dumpActivity(String prefix, FileDescriptor fd, PrintWriter pw,
8008 ActivityRecord r, String[] args, boolean dumpAll) {
8009 synchronized (this) {
8010 pw.print(prefix); pw.print("* Activity ");
8011 pw.print(Integer.toHexString(System.identityHashCode(r)));
8012 pw.print(" "); pw.print(r.shortComponentName); pw.print(" pid=");
8013 if (r.app != null) pw.println(r.app.pid);
8014 else pw.println("(not running)");
8015 if (dumpAll) {
8016 r.dump(pw, prefix + " ");
Dianne Hackborn625ac272010-09-17 18:29:22 -07008017 }
Dianne Hackborn625ac272010-09-17 18:29:22 -07008018 }
8019 if (r.app != null && r.app.thread != null) {
8020 try {
8021 // flush anything that is already in the PrintWriter since the thread is going
8022 // to write to the file descriptor directly
8023 pw.flush();
Dianne Hackborn30d71892010-12-11 10:37:55 -08008024 r.app.thread.dumpActivity(fd, r, prefix + " ", args);
Dianne Hackborn625ac272010-09-17 18:29:22 -07008025 pw.flush();
8026 } catch (RemoteException e) {
8027 pw.println("got a RemoteException while dumping the activity");
8028 }
8029 }
8030 }
8031
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008032 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8033 int opti, boolean dumpAll) {
8034 boolean needSep = false;
8035
8036 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008037 if (mRegisteredReceivers.size() > 0) {
8038 pw.println(" ");
8039 pw.println(" Registered Receivers:");
8040 Iterator it = mRegisteredReceivers.values().iterator();
8041 while (it.hasNext()) {
8042 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008043 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008044 r.dump(pw, " ");
8045 }
8046 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008047
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008048 pw.println(" ");
8049 pw.println("Receiver Resolver Table:");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008050 mReceiverResolver.dump(pw, null, " ", null, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008051 needSep = true;
8052 }
8053
8054 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
8055 || mPendingBroadcast != null) {
8056 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008057 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008058 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008059 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008060 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
8061 pw.println(" Broadcast #" + i + ":");
8062 mParallelBroadcasts.get(i).dump(pw, " ");
8063 }
8064 if (mOrderedBroadcasts.size() > 0) {
8065 pw.println(" ");
Dianne Hackborn399cccb2010-04-13 22:57:49 -07008066 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008067 }
8068 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
8069 pw.println(" Serialized Broadcast #" + i + ":");
8070 mOrderedBroadcasts.get(i).dump(pw, " ");
8071 }
8072 pw.println(" ");
8073 pw.println(" Pending broadcast:");
8074 if (mPendingBroadcast != null) {
8075 mPendingBroadcast.dump(pw, " ");
8076 } else {
8077 pw.println(" (null)");
8078 }
8079 needSep = true;
8080 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008081
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008082 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008083 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08008084 pw.println(" Historical broadcasts:");
8085 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
8086 BroadcastRecord r = mBroadcastHistory[i];
8087 if (r == null) {
8088 break;
8089 }
8090 pw.println(" Historical Broadcast #" + i + ":");
8091 r.dump(pw, " ");
8092 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008093 needSep = true;
8094 }
8095
8096 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08008097 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008098 pw.println(" Sticky broadcasts:");
8099 StringBuilder sb = new StringBuilder(128);
8100 for (Map.Entry<String, ArrayList<Intent>> ent
8101 : mStickyBroadcasts.entrySet()) {
8102 pw.print(" * Sticky action "); pw.print(ent.getKey());
8103 pw.println(":");
8104 ArrayList<Intent> intents = ent.getValue();
8105 final int N = intents.size();
8106 for (int i=0; i<N; i++) {
8107 sb.setLength(0);
8108 sb.append(" Intent: ");
8109 intents.get(i).toShortString(sb, true, false);
8110 pw.println(sb.toString());
8111 Bundle bundle = intents.get(i).getExtras();
8112 if (bundle != null) {
8113 pw.print(" ");
8114 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008115 }
8116 }
8117 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008118 needSep = true;
8119 }
8120
8121 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008122 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008123 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008124 pw.println(" mHandler:");
8125 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008126 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008127 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008128
8129 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008130 }
8131
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008132 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8133 int opti, boolean dumpAll) {
8134 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008135
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008136 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008137 if (mServices.size() > 0) {
8138 pw.println(" Active services:");
8139 Iterator<ServiceRecord> it = mServices.values().iterator();
8140 while (it.hasNext()) {
8141 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008142 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008143 r.dump(pw, " ");
8144 }
8145 needSep = true;
8146 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008147 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008148
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008149 if (mPendingServices.size() > 0) {
8150 if (needSep) pw.println(" ");
8151 pw.println(" Pending services:");
8152 for (int i=0; i<mPendingServices.size(); i++) {
8153 ServiceRecord r = mPendingServices.get(i);
8154 pw.print(" * Pending "); pw.println(r);
8155 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008156 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008157 needSep = true;
8158 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008159
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008160 if (mRestartingServices.size() > 0) {
8161 if (needSep) pw.println(" ");
8162 pw.println(" Restarting services:");
8163 for (int i=0; i<mRestartingServices.size(); i++) {
8164 ServiceRecord r = mRestartingServices.get(i);
8165 pw.print(" * Restarting "); pw.println(r);
8166 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008167 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008168 needSep = true;
8169 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008170
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008171 if (mStoppingServices.size() > 0) {
8172 if (needSep) pw.println(" ");
8173 pw.println(" Stopping services:");
8174 for (int i=0; i<mStoppingServices.size(); i++) {
8175 ServiceRecord r = mStoppingServices.get(i);
8176 pw.print(" * Stopping "); pw.println(r);
8177 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008178 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008179 needSep = true;
8180 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008181
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008182 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008183 if (mServiceConnections.size() > 0) {
8184 if (needSep) pw.println(" ");
8185 pw.println(" Connection bindings to services:");
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008186 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008187 = mServiceConnections.values().iterator();
8188 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008189 ArrayList<ConnectionRecord> r = it.next();
8190 for (int i=0; i<r.size(); i++) {
8191 pw.print(" * "); pw.println(r.get(i));
8192 r.get(i).dump(pw, " ");
8193 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008194 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008195 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008196 }
8197 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008198
8199 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008200 }
8201
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008202 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8203 int opti, boolean dumpAll) {
8204 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008205
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008206 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008207 if (mProvidersByClass.size() > 0) {
8208 if (needSep) pw.println(" ");
8209 pw.println(" Published content providers (by class):");
Dianne Hackborn860755f2010-06-03 18:47:52 -07008210 Iterator<Map.Entry<String, ContentProviderRecord>> it
8211 = mProvidersByClass.entrySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008212 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008213 Map.Entry<String, ContentProviderRecord> e = it.next();
8214 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008215 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008216 r.dump(pw, " ");
8217 }
8218 needSep = true;
8219 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008220
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008221 if (mProvidersByName.size() > 0) {
8222 pw.println(" ");
8223 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -07008224 Iterator<Map.Entry<String, ContentProviderRecord>> it
8225 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008226 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008227 Map.Entry<String, ContentProviderRecord> e = it.next();
8228 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008229 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
8230 pw.println(r);
8231 }
8232 needSep = true;
8233 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008234 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008235
8236 if (mLaunchingProviders.size() > 0) {
8237 if (needSep) pw.println(" ");
8238 pw.println(" Launching content providers:");
8239 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
8240 pw.print(" Launching #"); pw.print(i); pw.print(": ");
8241 pw.println(mLaunchingProviders.get(i));
8242 }
8243 needSep = true;
8244 }
8245
8246 if (mGrantedUriPermissions.size() > 0) {
8247 pw.println();
8248 pw.println("Granted Uri Permissions:");
8249 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
8250 int uid = mGrantedUriPermissions.keyAt(i);
8251 HashMap<Uri, UriPermission> perms
8252 = mGrantedUriPermissions.valueAt(i);
8253 pw.print(" * UID "); pw.print(uid);
8254 pw.println(" holds:");
8255 for (UriPermission perm : perms.values()) {
8256 pw.print(" "); pw.println(perm);
8257 perm.dump(pw, " ");
8258 }
8259 }
8260 needSep = true;
8261 }
8262
8263 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008264 }
8265
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008266 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8267 int opti, boolean dumpAll) {
8268 boolean needSep = false;
8269
8270 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008271 if (this.mIntentSenderRecords.size() > 0) {
8272 Iterator<WeakReference<PendingIntentRecord>> it
8273 = mIntentSenderRecords.values().iterator();
8274 while (it.hasNext()) {
8275 WeakReference<PendingIntentRecord> ref = it.next();
8276 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008277 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008278 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008279 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008280 rec.dump(pw, " ");
8281 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008282 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008283 }
8284 }
8285 }
8286 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008287
8288 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008289 }
8290
8291 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008292 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008293 TaskRecord lastTask = null;
8294 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008295 ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008296 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008297 if (lastTask != r.task) {
8298 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008299 pw.print(prefix);
8300 pw.print(full ? "* " : " ");
8301 pw.println(lastTask);
8302 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008303 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008304 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008305 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008306 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
8307 pw.print(" #"); pw.print(i); pw.print(": ");
8308 pw.println(r);
8309 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008310 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008311 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008312 }
8313 }
8314
Dianne Hackborn09c916b2009-12-08 14:50:51 -08008315 private static String buildOomTag(String prefix, String space, int val, int base) {
8316 if (val == base) {
8317 if (space == null) return prefix;
8318 return prefix + " ";
8319 }
8320 return prefix + "+" + Integer.toString(val-base);
8321 }
8322
8323 private static final int dumpProcessList(PrintWriter pw,
8324 ActivityManagerService service, List list,
Dianne Hackborn287952c2010-09-22 22:34:31 -07008325 String prefix, String normalLabel, String persistentLabel) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008326 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07008327 final int N = list.size()-1;
8328 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008329 ProcessRecord r = (ProcessRecord)list.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008330 pw.println(String.format("%s%s #%2d: %s",
8331 prefix, (r.persistent ? persistentLabel : normalLabel),
8332 i, r.toString()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008333 if (r.persistent) {
8334 numPers++;
8335 }
8336 }
8337 return numPers;
8338 }
8339
Dianne Hackborn287952c2010-09-22 22:34:31 -07008340 private static final void dumpProcessOomList(PrintWriter pw,
8341 ActivityManagerService service, List<ProcessRecord> list,
8342 String prefix, String normalLabel, String persistentLabel,
8343 boolean inclDetails) {
8344
8345 final long curRealtime = SystemClock.elapsedRealtime();
8346 final long realtimeSince = curRealtime - service.mLastPowerCheckRealtime;
8347 final long curUptime = SystemClock.uptimeMillis();
8348 final long uptimeSince = curUptime - service.mLastPowerCheckUptime;
8349
8350 final int N = list.size()-1;
8351 for (int i=N; i>=0; i--) {
8352 ProcessRecord r = list.get(i);
8353 String oomAdj;
8354 if (r.setAdj >= EMPTY_APP_ADJ) {
8355 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
8356 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
8357 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
8358 } else if (r.setAdj >= HOME_APP_ADJ) {
8359 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
8360 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
8361 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
8362 } else if (r.setAdj >= BACKUP_APP_ADJ) {
8363 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
8364 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
8365 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
8366 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
8367 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
8368 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
8369 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
8370 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
8371 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
8372 } else if (r.setAdj >= CORE_SERVER_ADJ) {
8373 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
8374 } else if (r.setAdj >= SYSTEM_ADJ) {
8375 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
8376 } else {
8377 oomAdj = Integer.toString(r.setAdj);
8378 }
8379 String schedGroup;
8380 switch (r.setSchedGroup) {
8381 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
8382 schedGroup = "B";
8383 break;
8384 case Process.THREAD_GROUP_DEFAULT:
8385 schedGroup = "F";
8386 break;
8387 default:
8388 schedGroup = Integer.toString(r.setSchedGroup);
8389 break;
8390 }
8391 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
8392 prefix, (r.persistent ? persistentLabel : normalLabel),
8393 N-i, oomAdj, schedGroup, r.toShortString(), r.adjType));
8394 if (r.adjSource != null || r.adjTarget != null) {
8395 pw.print(prefix);
8396 pw.print(" ");
8397 if (r.adjTarget instanceof ComponentName) {
8398 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
8399 } else if (r.adjTarget != null) {
8400 pw.print(r.adjTarget.toString());
8401 } else {
8402 pw.print("{null}");
8403 }
8404 pw.print("<=");
8405 if (r.adjSource instanceof ProcessRecord) {
8406 pw.print("Proc{");
8407 pw.print(((ProcessRecord)r.adjSource).toShortString());
8408 pw.println("}");
8409 } else if (r.adjSource != null) {
8410 pw.println(r.adjSource.toString());
8411 } else {
8412 pw.println("{null}");
8413 }
8414 }
8415 if (inclDetails) {
8416 pw.print(prefix);
8417 pw.print(" ");
8418 pw.print("oom: max="); pw.print(r.maxAdj);
8419 pw.print(" hidden="); pw.print(r.hiddenAdj);
8420 pw.print(" curRaw="); pw.print(r.curRawAdj);
8421 pw.print(" setRaw="); pw.print(r.setRawAdj);
8422 pw.print(" cur="); pw.print(r.curAdj);
8423 pw.print(" set="); pw.println(r.setAdj);
8424 pw.print(prefix);
8425 pw.print(" ");
8426 pw.print("keeping="); pw.print(r.keeping);
8427 pw.print(" hidden="); pw.print(r.hidden);
8428 pw.print(" empty="); pw.println(r.empty);
8429
8430 if (!r.keeping) {
8431 if (r.lastWakeTime != 0) {
8432 long wtime;
8433 BatteryStatsImpl stats = service.mBatteryStatsService.getActiveStatistics();
8434 synchronized (stats) {
8435 wtime = stats.getProcessWakeTime(r.info.uid,
8436 r.pid, curRealtime);
8437 }
8438 long timeUsed = wtime - r.lastWakeTime;
8439 pw.print(prefix);
8440 pw.print(" ");
8441 pw.print("keep awake over ");
8442 TimeUtils.formatDuration(realtimeSince, pw);
8443 pw.print(" used ");
8444 TimeUtils.formatDuration(timeUsed, pw);
8445 pw.print(" (");
8446 pw.print((timeUsed*100)/realtimeSince);
8447 pw.println("%)");
8448 }
8449 if (r.lastCpuTime != 0) {
8450 long timeUsed = r.curCpuTime - r.lastCpuTime;
8451 pw.print(prefix);
8452 pw.print(" ");
8453 pw.print("run cpu over ");
8454 TimeUtils.formatDuration(uptimeSince, pw);
8455 pw.print(" used ");
8456 TimeUtils.formatDuration(timeUsed, pw);
8457 pw.print(" (");
8458 pw.print((timeUsed*100)/uptimeSince);
8459 pw.println("%)");
8460 }
8461 }
8462 }
8463 }
8464 }
8465
Dianne Hackborn472ad872010-04-07 17:31:48 -07008466 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008467 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -07008468 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008469 long uptime = SystemClock.uptimeMillis();
8470 long realtime = SystemClock.elapsedRealtime();
8471
8472 if (isCheckinRequest) {
8473 // short checkin version
8474 pw.println(uptime + "," + realtime);
8475 pw.flush();
8476 } else {
8477 pw.println("Applications Memory Usage (kB):");
8478 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
8479 }
8480 for (int i = list.size() - 1 ; i >= 0 ; i--) {
8481 ProcessRecord r = (ProcessRecord)list.get(i);
8482 if (r.thread != null) {
8483 if (!isCheckinRequest) {
8484 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
8485 pw.flush();
8486 }
8487 try {
8488 r.thread.asBinder().dump(fd, args);
8489 } catch (RemoteException e) {
8490 if (!isCheckinRequest) {
8491 pw.println("Got RemoteException!");
8492 pw.flush();
8493 }
8494 }
8495 }
8496 }
8497 }
8498
8499 /**
8500 * Searches array of arguments for the specified string
8501 * @param args array of argument strings
8502 * @param value value to search for
8503 * @return true if the value is contained in the array
8504 */
8505 private static boolean scanArgs(String[] args, String value) {
8506 if (args != null) {
8507 for (String arg : args) {
8508 if (value.equals(arg)) {
8509 return true;
8510 }
8511 }
8512 }
8513 return false;
8514 }
8515
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008516 private final void killServicesLocked(ProcessRecord app,
8517 boolean allowRestart) {
8518 // Report disconnected services.
8519 if (false) {
8520 // XXX we are letting the client link to the service for
8521 // death notifications.
8522 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008523 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008524 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008525 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008526 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008527 Iterator<ArrayList<ConnectionRecord>> jt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008528 = r.connections.values().iterator();
8529 while (jt.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008530 ArrayList<ConnectionRecord> cl = jt.next();
8531 for (int i=0; i<cl.size(); i++) {
8532 ConnectionRecord c = cl.get(i);
8533 if (c.binding.client != app) {
8534 try {
8535 //c.conn.connected(r.className, null);
8536 } catch (Exception e) {
8537 // todo: this should be asynchronous!
8538 Slog.w(TAG, "Exception thrown disconnected servce "
8539 + r.shortName
8540 + " from app " + app.processName, e);
8541 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008542 }
8543 }
8544 }
8545 }
8546 }
8547 }
8548 }
8549
8550 // Clean up any connections this application has to other services.
8551 if (app.connections.size() > 0) {
8552 Iterator<ConnectionRecord> it = app.connections.iterator();
8553 while (it.hasNext()) {
8554 ConnectionRecord r = it.next();
8555 removeConnectionLocked(r, app, null);
8556 }
8557 }
8558 app.connections.clear();
8559
8560 if (app.services.size() != 0) {
8561 // Any services running in the application need to be placed
8562 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07008563 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008564 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008565 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008566 synchronized (sr.stats.getBatteryStats()) {
8567 sr.stats.stopLaunchedLocked();
8568 }
8569 sr.app = null;
8570 sr.executeNesting = 0;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008571 if (mStoppingServices.remove(sr)) {
8572 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
8573 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008574
8575 boolean hasClients = sr.bindings.size() > 0;
8576 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008577 Iterator<IntentBindRecord> bindings
8578 = sr.bindings.values().iterator();
8579 while (bindings.hasNext()) {
8580 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008581 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008582 + ": shouldUnbind=" + b.hasBound);
8583 b.binder = null;
8584 b.requested = b.received = b.hasBound = false;
8585 }
8586 }
8587
Dianne Hackborn070783f2010-12-29 16:46:28 -08008588 if (sr.crashCount >= 2 && (sr.serviceInfo.applicationInfo.flags
8589 &ApplicationInfo.FLAG_PERSISTENT) == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008590 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008591 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008592 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008593 sr.crashCount, sr.shortName, app.pid);
8594 bringDownServiceLocked(sr, true);
8595 } else if (!allowRestart) {
8596 bringDownServiceLocked(sr, true);
8597 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008598 boolean canceled = scheduleServiceRestartLocked(sr, true);
8599
8600 // Should the service remain running? Note that in the
8601 // extreme case of so many attempts to deliver a command
8602 // that it failed, that we also will stop it here.
8603 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
8604 if (sr.pendingStarts.size() == 0) {
8605 sr.startRequested = false;
8606 if (!hasClients) {
8607 // Whoops, no reason to restart!
8608 bringDownServiceLocked(sr, true);
8609 }
8610 }
8611 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008612 }
8613 }
8614
8615 if (!allowRestart) {
8616 app.services.clear();
8617 }
8618 }
8619
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008620 // Make sure we have no more records on the stopping list.
8621 int i = mStoppingServices.size();
8622 while (i > 0) {
8623 i--;
8624 ServiceRecord sr = mStoppingServices.get(i);
8625 if (sr.app == app) {
8626 mStoppingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008627 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008628 }
8629 }
8630
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008631 app.executingServices.clear();
8632 }
8633
8634 private final void removeDyingProviderLocked(ProcessRecord proc,
8635 ContentProviderRecord cpr) {
8636 synchronized (cpr) {
8637 cpr.launchingApp = null;
8638 cpr.notifyAll();
8639 }
8640
8641 mProvidersByClass.remove(cpr.info.name);
8642 String names[] = cpr.info.authority.split(";");
8643 for (int j = 0; j < names.length; j++) {
8644 mProvidersByName.remove(names[j]);
8645 }
8646
8647 Iterator<ProcessRecord> cit = cpr.clients.iterator();
8648 while (cit.hasNext()) {
8649 ProcessRecord capp = cit.next();
8650 if (!capp.persistent && capp.thread != null
8651 && capp.pid != 0
8652 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07008653 Slog.i(TAG, "Kill " + capp.processName
8654 + " (pid " + capp.pid + "): provider " + cpr.info.name
8655 + " in dying process " + proc.processName);
8656 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
8657 capp.processName, capp.setAdj, "dying provider " + proc.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008658 Process.killProcess(capp.pid);
8659 }
8660 }
8661
8662 mLaunchingProviders.remove(cpr);
8663 }
8664
8665 /**
8666 * Main code for cleaning up a process when it has gone away. This is
8667 * called both as a result of the process dying, or directly when stopping
8668 * a process when running in single process mode.
8669 */
8670 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
8671 boolean restarting, int index) {
8672 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008673 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008674 }
8675
Dianne Hackborn36124872009-10-08 16:22:03 -07008676 mProcessesToGc.remove(app);
8677
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008678 // Dismiss any open dialogs.
8679 if (app.crashDialog != null) {
8680 app.crashDialog.dismiss();
8681 app.crashDialog = null;
8682 }
8683 if (app.anrDialog != null) {
8684 app.anrDialog.dismiss();
8685 app.anrDialog = null;
8686 }
8687 if (app.waitDialog != null) {
8688 app.waitDialog.dismiss();
8689 app.waitDialog = null;
8690 }
8691
8692 app.crashing = false;
8693 app.notResponding = false;
8694
8695 app.resetPackageList();
8696 app.thread = null;
8697 app.forcingToForeground = null;
8698 app.foregroundServices = false;
8699
8700 killServicesLocked(app, true);
8701
8702 boolean restart = false;
8703
8704 int NL = mLaunchingProviders.size();
8705
8706 // Remove published content providers.
8707 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008708 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008709 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008710 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008711 cpr.provider = null;
8712 cpr.app = null;
8713
8714 // See if someone is waiting for this provider... in which
8715 // case we don't remove it, but just let it restart.
8716 int i = 0;
8717 if (!app.bad) {
8718 for (; i<NL; i++) {
8719 if (mLaunchingProviders.get(i) == cpr) {
8720 restart = true;
8721 break;
8722 }
8723 }
8724 } else {
8725 i = NL;
8726 }
8727
8728 if (i >= NL) {
8729 removeDyingProviderLocked(app, cpr);
8730 NL = mLaunchingProviders.size();
8731 }
8732 }
8733 app.pubProviders.clear();
8734 }
8735
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008736 // Take care of any launching providers waiting for this process.
8737 if (checkAppInLaunchingProvidersLocked(app, false)) {
8738 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008739 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008740
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008741 // Unregister from connected content providers.
8742 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008743 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008744 while (it.hasNext()) {
8745 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
8746 cpr.clients.remove(app);
8747 }
8748 app.conProviders.clear();
8749 }
8750
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008751 // At this point there may be remaining entries in mLaunchingProviders
8752 // where we were the only one waiting, so they are no longer of use.
8753 // Look for these and clean up if found.
8754 // XXX Commented out for now. Trying to figure out a way to reproduce
8755 // the actual situation to identify what is actually going on.
8756 if (false) {
8757 for (int i=0; i<NL; i++) {
8758 ContentProviderRecord cpr = (ContentProviderRecord)
8759 mLaunchingProviders.get(i);
8760 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
8761 synchronized (cpr) {
8762 cpr.launchingApp = null;
8763 cpr.notifyAll();
8764 }
8765 }
8766 }
8767 }
8768
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008769 skipCurrentReceiverLocked(app);
8770
8771 // Unregister any receivers.
8772 if (app.receivers.size() > 0) {
8773 Iterator<ReceiverList> it = app.receivers.iterator();
8774 while (it.hasNext()) {
8775 removeReceiverLocked(it.next());
8776 }
8777 app.receivers.clear();
8778 }
8779
Christopher Tate181fafa2009-05-14 11:12:14 -07008780 // If the app is undergoing backup, tell the backup manager about it
8781 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008782 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -07008783 try {
8784 IBackupManager bm = IBackupManager.Stub.asInterface(
8785 ServiceManager.getService(Context.BACKUP_SERVICE));
8786 bm.agentDisconnected(app.info.packageName);
8787 } catch (RemoteException e) {
8788 // can't happen; backup manager is local
8789 }
8790 }
8791
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008792 // If the caller is restarting this app, then leave it in its
8793 // current lists and let the caller take care of it.
8794 if (restarting) {
8795 return;
8796 }
8797
8798 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008799 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008800 "Removing non-persistent process during cleanup: " + app);
8801 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07008802 if (mHeavyWeightProcess == app) {
8803 mHeavyWeightProcess = null;
8804 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
8805 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008806 } else if (!app.removed) {
8807 // This app is persistent, so we need to keep its record around.
8808 // If it is not already on the pending app list, add it there
8809 // and start a new process for it.
8810 app.thread = null;
8811 app.forcingToForeground = null;
8812 app.foregroundServices = false;
8813 if (mPersistentStartingProcesses.indexOf(app) < 0) {
8814 mPersistentStartingProcesses.add(app);
8815 restart = true;
8816 }
8817 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07008818 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
8819 "Clean-up removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008820 mProcessesOnHold.remove(app);
8821
The Android Open Source Project4df24232009-03-05 14:34:35 -08008822 if (app == mHomeProcess) {
8823 mHomeProcess = null;
8824 }
8825
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008826 if (restart) {
8827 // We have components that still need to be running in the
8828 // process, so re-launch it.
8829 mProcessNames.put(app.processName, app.info.uid, app);
8830 startProcessLocked(app, "restart", app.processName);
8831 } else if (app.pid > 0 && app.pid != MY_PID) {
8832 // Goodbye!
8833 synchronized (mPidsSelfLocked) {
8834 mPidsSelfLocked.remove(app.pid);
8835 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
8836 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008837 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008838 }
8839 }
8840
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008841 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
8842 // Look through the content providers we are waiting to have launched,
8843 // and if any run in this process then either schedule a restart of
8844 // the process or kill the client waiting for it if this process has
8845 // gone bad.
8846 int NL = mLaunchingProviders.size();
8847 boolean restart = false;
8848 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008849 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008850 if (cpr.launchingApp == app) {
8851 if (!alwaysBad && !app.bad) {
8852 restart = true;
8853 } else {
8854 removeDyingProviderLocked(app, cpr);
8855 NL = mLaunchingProviders.size();
8856 }
8857 }
8858 }
8859 return restart;
8860 }
8861
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008862 // =========================================================
8863 // SERVICES
8864 // =========================================================
8865
8866 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
8867 ActivityManager.RunningServiceInfo info =
8868 new ActivityManager.RunningServiceInfo();
8869 info.service = r.name;
8870 if (r.app != null) {
8871 info.pid = r.app.pid;
8872 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008873 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008874 info.process = r.processName;
8875 info.foreground = r.isForeground;
8876 info.activeSince = r.createTime;
8877 info.started = r.startRequested;
8878 info.clientCount = r.connections.size();
8879 info.crashCount = r.crashCount;
8880 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008881 if (r.isForeground) {
8882 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
8883 }
8884 if (r.startRequested) {
8885 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
8886 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008887 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008888 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
8889 }
8890 if (r.app != null && r.app.persistent) {
8891 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
8892 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008893
8894 for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
8895 for (int i=0; i<connl.size(); i++) {
8896 ConnectionRecord conn = connl.get(i);
8897 if (conn.clientLabel != 0) {
8898 info.clientPackage = conn.binding.client.info.packageName;
8899 info.clientLabel = conn.clientLabel;
8900 return info;
8901 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008902 }
8903 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008904 return info;
8905 }
8906
8907 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
8908 int flags) {
8909 synchronized (this) {
8910 ArrayList<ActivityManager.RunningServiceInfo> res
8911 = new ArrayList<ActivityManager.RunningServiceInfo>();
8912
8913 if (mServices.size() > 0) {
8914 Iterator<ServiceRecord> it = mServices.values().iterator();
8915 while (it.hasNext() && res.size() < maxNum) {
8916 res.add(makeRunningServiceInfoLocked(it.next()));
8917 }
8918 }
8919
8920 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
8921 ServiceRecord r = mRestartingServices.get(i);
8922 ActivityManager.RunningServiceInfo info =
8923 makeRunningServiceInfoLocked(r);
8924 info.restarting = r.nextRestartTime;
8925 res.add(info);
8926 }
8927
8928 return res;
8929 }
8930 }
8931
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008932 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
8933 synchronized (this) {
8934 ServiceRecord r = mServices.get(name);
8935 if (r != null) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008936 for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
8937 for (int i=0; i<conn.size(); i++) {
8938 if (conn.get(i).clientIntent != null) {
8939 return conn.get(i).clientIntent;
8940 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008941 }
8942 }
8943 }
8944 }
8945 return null;
8946 }
8947
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008948 private final ServiceRecord findServiceLocked(ComponentName name,
8949 IBinder token) {
8950 ServiceRecord r = mServices.get(name);
8951 return r == token ? r : null;
8952 }
8953
8954 private final class ServiceLookupResult {
8955 final ServiceRecord record;
8956 final String permission;
8957
8958 ServiceLookupResult(ServiceRecord _record, String _permission) {
8959 record = _record;
8960 permission = _permission;
8961 }
8962 };
8963
8964 private ServiceLookupResult findServiceLocked(Intent service,
8965 String resolvedType) {
8966 ServiceRecord r = null;
8967 if (service.getComponent() != null) {
8968 r = mServices.get(service.getComponent());
8969 }
8970 if (r == null) {
8971 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8972 r = mServicesByIntent.get(filter);
8973 }
8974
8975 if (r == null) {
8976 try {
8977 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008978 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008979 service, resolvedType, 0);
8980 ServiceInfo sInfo =
8981 rInfo != null ? rInfo.serviceInfo : null;
8982 if (sInfo == null) {
8983 return null;
8984 }
8985
8986 ComponentName name = new ComponentName(
8987 sInfo.applicationInfo.packageName, sInfo.name);
8988 r = mServices.get(name);
8989 } catch (RemoteException ex) {
8990 // pm is in same process, this will never happen.
8991 }
8992 }
8993 if (r != null) {
8994 int callingPid = Binder.getCallingPid();
8995 int callingUid = Binder.getCallingUid();
8996 if (checkComponentPermission(r.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08008997 callingPid, callingUid, r.appInfo.uid, r.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008998 != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08008999 if (!r.exported) {
9000 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
9001 + " from pid=" + callingPid
9002 + ", uid=" + callingUid
9003 + " that is not exported from uid " + r.appInfo.uid);
9004 return new ServiceLookupResult(null, "not exported from uid "
9005 + r.appInfo.uid);
9006 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009007 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009008 + " from pid=" + callingPid
9009 + ", uid=" + callingUid
9010 + " requires " + r.permission);
9011 return new ServiceLookupResult(null, r.permission);
9012 }
9013 return new ServiceLookupResult(r, null);
9014 }
9015 return null;
9016 }
9017
9018 private class ServiceRestarter implements Runnable {
9019 private ServiceRecord mService;
9020
9021 void setService(ServiceRecord service) {
9022 mService = service;
9023 }
9024
9025 public void run() {
9026 synchronized(ActivityManagerService.this) {
9027 performServiceRestartLocked(mService);
9028 }
9029 }
9030 }
9031
9032 private ServiceLookupResult retrieveServiceLocked(Intent service,
9033 String resolvedType, int callingPid, int callingUid) {
9034 ServiceRecord r = null;
9035 if (service.getComponent() != null) {
9036 r = mServices.get(service.getComponent());
9037 }
9038 Intent.FilterComparison filter = new Intent.FilterComparison(service);
9039 r = mServicesByIntent.get(filter);
9040 if (r == null) {
9041 try {
9042 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009043 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -07009044 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009045 ServiceInfo sInfo =
9046 rInfo != null ? rInfo.serviceInfo : null;
9047 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009048 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009049 ": not found");
9050 return null;
9051 }
9052
9053 ComponentName name = new ComponentName(
9054 sInfo.applicationInfo.packageName, sInfo.name);
9055 r = mServices.get(name);
9056 if (r == null) {
9057 filter = new Intent.FilterComparison(service.cloneFilter());
9058 ServiceRestarter res = new ServiceRestarter();
9059 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
9060 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
9061 synchronized (stats) {
9062 ss = stats.getServiceStatsLocked(
9063 sInfo.applicationInfo.uid, sInfo.packageName,
9064 sInfo.name);
9065 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -08009066 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009067 res.setService(r);
9068 mServices.put(name, r);
9069 mServicesByIntent.put(filter, r);
9070
9071 // Make sure this component isn't in the pending list.
9072 int N = mPendingServices.size();
9073 for (int i=0; i<N; i++) {
9074 ServiceRecord pr = mPendingServices.get(i);
9075 if (pr.name.equals(name)) {
9076 mPendingServices.remove(i);
9077 i--;
9078 N--;
9079 }
9080 }
9081 }
9082 } catch (RemoteException ex) {
9083 // pm is in same process, this will never happen.
9084 }
9085 }
9086 if (r != null) {
9087 if (checkComponentPermission(r.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009088 callingPid, callingUid, r.appInfo.uid, r.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009089 != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009090 if (!r.exported) {
9091 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
9092 + " from pid=" + callingPid
9093 + ", uid=" + callingUid
9094 + " that is not exported from uid " + r.appInfo.uid);
9095 return new ServiceLookupResult(null, "not exported from uid "
9096 + r.appInfo.uid);
9097 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009098 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009099 + " from pid=" + callingPid
9100 + ", uid=" + callingUid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009101 + " requires " + r.permission);
9102 return new ServiceLookupResult(null, r.permission);
9103 }
9104 return new ServiceLookupResult(r, null);
9105 }
9106 return null;
9107 }
9108
Dianne Hackborn287952c2010-09-22 22:34:31 -07009109 private final void bumpServiceExecutingLocked(ServiceRecord r, String why) {
9110 if (DEBUG_SERVICE) Log.v(TAG, ">>> EXECUTING "
9111 + why + " of " + r + " in app " + r.app);
9112 else if (DEBUG_SERVICE_EXECUTING) Log.v(TAG, ">>> EXECUTING "
9113 + why + " of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009114 long now = SystemClock.uptimeMillis();
9115 if (r.executeNesting == 0 && r.app != null) {
9116 if (r.app.executingServices.size() == 0) {
9117 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
9118 msg.obj = r.app;
9119 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
9120 }
9121 r.app.executingServices.add(r);
9122 }
9123 r.executeNesting++;
9124 r.executingStart = now;
9125 }
9126
9127 private final void sendServiceArgsLocked(ServiceRecord r,
9128 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009129 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009130 if (N == 0) {
9131 return;
9132 }
9133
Dianne Hackborn39792d22010-08-19 18:01:52 -07009134 while (r.pendingStarts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009135 try {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009136 ServiceRecord.StartItem si = r.pendingStarts.remove(0);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009137 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
9138 + r + " " + r.intent + " args=" + si.intent);
Dianne Hackborn3a28f222011-03-01 12:25:54 -08009139 if (si.intent == null && N > 1) {
9140 // If somehow we got a dummy null intent in the middle,
9141 // then skip it. DO NOT skip a null intent when it is
9142 // the only one in the list -- this is to support the
9143 // onStartCommand(null) case.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009144 continue;
9145 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009146 si.deliveredTime = SystemClock.uptimeMillis();
9147 r.deliveredStarts.add(si);
9148 si.deliveryCount++;
Dianne Hackborn3a28f222011-03-01 12:25:54 -08009149 if (si.targetPermissionUid >= 0 && si.intent != null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009150 grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
Dianne Hackborn7e269642010-08-25 19:50:20 -07009151 r.packageName, si.intent, si.getUriPermissionsLocked());
Dianne Hackborn39792d22010-08-19 18:01:52 -07009152 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07009153 bumpServiceExecutingLocked(r, "start");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009154 if (!oomAdjusted) {
9155 oomAdjusted = true;
9156 updateOomAdjLocked(r.app);
9157 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009158 int flags = 0;
9159 if (si.deliveryCount > 0) {
9160 flags |= Service.START_FLAG_RETRY;
9161 }
9162 if (si.doneExecutingCount > 0) {
9163 flags |= Service.START_FLAG_REDELIVERY;
9164 }
9165 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009166 } catch (RemoteException e) {
9167 // Remote process gone... we'll let the normal cleanup take
9168 // care of this.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009169 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009170 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009171 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009172 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009173 break;
9174 }
9175 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009176 }
9177
9178 private final boolean requestServiceBindingLocked(ServiceRecord r,
9179 IntentBindRecord i, boolean rebind) {
9180 if (r.app == null || r.app.thread == null) {
9181 // If service is not currently running, can't yet bind.
9182 return false;
9183 }
9184 if ((!i.requested || rebind) && i.apps.size() > 0) {
9185 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009186 bumpServiceExecutingLocked(r, "bind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009187 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
9188 if (!rebind) {
9189 i.requested = true;
9190 }
9191 i.hasBound = true;
9192 i.doRebind = false;
9193 } catch (RemoteException e) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009194 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009195 return false;
9196 }
9197 }
9198 return true;
9199 }
9200
9201 private final void requestServiceBindingsLocked(ServiceRecord r) {
9202 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
9203 while (bindings.hasNext()) {
9204 IntentBindRecord i = bindings.next();
9205 if (!requestServiceBindingLocked(r, i, false)) {
9206 break;
9207 }
9208 }
9209 }
9210
9211 private final void realStartServiceLocked(ServiceRecord r,
9212 ProcessRecord app) throws RemoteException {
9213 if (app.thread == null) {
9214 throw new RemoteException();
9215 }
9216
9217 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -07009218 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009219
9220 app.services.add(r);
Dianne Hackborn287952c2010-09-22 22:34:31 -07009221 bumpServiceExecutingLocked(r, "create");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009222 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009223
9224 boolean created = false;
9225 try {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07009226 mStringBuilder.setLength(0);
9227 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009228 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009229 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -07009230 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009231 synchronized (r.stats.getBatteryStats()) {
9232 r.stats.startLaunchedLocked();
9233 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07009234 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009235 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009236 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009237 created = true;
9238 } finally {
9239 if (!created) {
9240 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009241 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009242 }
9243 }
9244
9245 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009246
9247 // If the service is in the started state, and there are no
9248 // pending arguments, then fake up one so its onStartCommand() will
9249 // be called.
9250 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
9251 r.lastStartId++;
9252 if (r.lastStartId < 1) {
9253 r.lastStartId = 1;
9254 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009255 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId, null, -1));
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009256 }
9257
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009258 sendServiceArgsLocked(r, true);
9259 }
9260
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009261 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
9262 boolean allowCancel) {
9263 boolean canceled = false;
9264
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009265 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009266 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -07009267 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009268
Dianne Hackborn070783f2010-12-29 16:46:28 -08009269 if ((r.serviceInfo.applicationInfo.flags
9270 &ApplicationInfo.FLAG_PERSISTENT) != 0) {
9271 minDuration /= 4;
9272 }
9273
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009274 // Any delivered but not yet finished starts should be put back
9275 // on the pending list.
9276 final int N = r.deliveredStarts.size();
9277 if (N > 0) {
9278 for (int i=N-1; i>=0; i--) {
9279 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
Dianne Hackborn39792d22010-08-19 18:01:52 -07009280 si.removeUriPermissionsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009281 if (si.intent == null) {
9282 // We'll generate this again if needed.
9283 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
9284 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
9285 r.pendingStarts.add(0, si);
9286 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
9287 dur *= 2;
9288 if (minDuration < dur) minDuration = dur;
9289 if (resetTime < dur) resetTime = dur;
9290 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009291 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009292 + r.name);
9293 canceled = true;
9294 }
9295 }
9296 r.deliveredStarts.clear();
9297 }
9298
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009299 r.totalRestartCount++;
9300 if (r.restartDelay == 0) {
9301 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009302 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009303 } else {
9304 // If it has been a "reasonably long time" since the service
9305 // was started, then reset our restart duration back to
9306 // the beginning, so we don't infinitely increase the duration
9307 // on a service that just occasionally gets killed (which is
9308 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009309 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009310 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009311 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009312 } else {
Dianne Hackborn070783f2010-12-29 16:46:28 -08009313 if ((r.serviceInfo.applicationInfo.flags
9314 &ApplicationInfo.FLAG_PERSISTENT) != 0) {
9315 // Services in peristent processes will restart much more
9316 // quickly, since they are pretty important. (Think SystemUI).
9317 r.restartDelay += minDuration/2;
9318 } else {
9319 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
9320 if (r.restartDelay < minDuration) {
9321 r.restartDelay = minDuration;
9322 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009323 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009324 }
9325 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009326
9327 r.nextRestartTime = now + r.restartDelay;
9328
9329 // Make sure that we don't end up restarting a bunch of services
9330 // all at the same time.
9331 boolean repeat;
9332 do {
9333 repeat = false;
9334 for (int i=mRestartingServices.size()-1; i>=0; i--) {
9335 ServiceRecord r2 = mRestartingServices.get(i);
9336 if (r2 != r && r.nextRestartTime
9337 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
9338 && r.nextRestartTime
9339 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
9340 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
9341 r.restartDelay = r.nextRestartTime - now;
9342 repeat = true;
9343 break;
9344 }
9345 }
9346 } while (repeat);
9347
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009348 if (!mRestartingServices.contains(r)) {
9349 mRestartingServices.add(r);
9350 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009351
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009352 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009353
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009354 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009355 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009356 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009357 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009358 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -08009359 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009360 r.shortName, r.restartDelay);
9361
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009362 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009363 }
9364
9365 final void performServiceRestartLocked(ServiceRecord r) {
9366 if (!mRestartingServices.contains(r)) {
9367 return;
9368 }
9369 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
9370 }
9371
9372 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
9373 if (r.restartDelay == 0) {
9374 return false;
9375 }
9376 r.resetRestartCounter();
9377 mRestartingServices.remove(r);
9378 mHandler.removeCallbacks(r.restarter);
9379 return true;
9380 }
9381
9382 private final boolean bringUpServiceLocked(ServiceRecord r,
9383 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009384 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009385 //r.dump(" ");
9386
Dianne Hackborn36124872009-10-08 16:22:03 -07009387 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009388 sendServiceArgsLocked(r, false);
9389 return true;
9390 }
9391
9392 if (!whileRestarting && r.restartDelay > 0) {
9393 // If waiting for a restart, then do nothing.
9394 return true;
9395 }
9396
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009397 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009398
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009399 // We are now bringing the service up, so no longer in the
9400 // restarting state.
9401 mRestartingServices.remove(r);
9402
Dianne Hackborne7f97212011-02-24 14:40:20 -08009403 // Service is now being launched, its package can't be stopped.
9404 try {
9405 AppGlobals.getPackageManager().setPackageStoppedState(
9406 r.packageName, false);
9407 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08009408 } catch (IllegalArgumentException e) {
9409 Slog.w(TAG, "Failed trying to unstop package "
9410 + r.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08009411 }
9412
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009413 final String appName = r.processName;
9414 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
9415 if (app != null && app.thread != null) {
9416 try {
9417 realStartServiceLocked(r, app);
9418 return true;
9419 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009420 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009421 }
9422
9423 // If a dead object exception was thrown -- fall through to
9424 // restart the application.
9425 }
9426
Dianne Hackborn36124872009-10-08 16:22:03 -07009427 // Not running -- get it started, and enqueue this service record
9428 // to be executed when the app comes up.
9429 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
9430 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009431 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -07009432 + r.appInfo.packageName + "/"
9433 + r.appInfo.uid + " for service "
9434 + r.intent.getIntent() + ": process is bad");
9435 bringDownServiceLocked(r, true);
9436 return false;
9437 }
9438
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009439 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009440 mPendingServices.add(r);
9441 }
Dianne Hackborn36124872009-10-08 16:22:03 -07009442
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009443 return true;
9444 }
9445
9446 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009447 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009448 //r.dump(" ");
9449
9450 // Does it still need to run?
9451 if (!force && r.startRequested) {
9452 return;
9453 }
9454 if (r.connections.size() > 0) {
9455 if (!force) {
9456 // XXX should probably keep a count of the number of auto-create
9457 // connections directly in the service.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009458 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009459 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009460 ArrayList<ConnectionRecord> cr = it.next();
9461 for (int i=0; i<cr.size(); i++) {
9462 if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
9463 return;
9464 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009465 }
9466 }
9467 }
9468
9469 // Report to all of the connections that the service is no longer
9470 // available.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009471 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009472 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009473 ArrayList<ConnectionRecord> c = it.next();
9474 for (int i=0; i<c.size(); i++) {
9475 try {
9476 c.get(i).conn.connected(r.name, null);
9477 } catch (Exception e) {
9478 Slog.w(TAG, "Failure disconnecting service " + r.name +
9479 " to connection " + c.get(i).conn.asBinder() +
9480 " (in " + c.get(i).binding.client.processName + ")", e);
9481 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009482 }
9483 }
9484 }
9485
9486 // Tell the service that it has been unbound.
9487 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
9488 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
9489 while (it.hasNext()) {
9490 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009491 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009492 + ": hasBound=" + ibr.hasBound);
9493 if (r.app != null && r.app.thread != null && ibr.hasBound) {
9494 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009495 bumpServiceExecutingLocked(r, "bring down unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009496 updateOomAdjLocked(r.app);
9497 ibr.hasBound = false;
9498 r.app.thread.scheduleUnbindService(r,
9499 ibr.intent.getIntent());
9500 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009501 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009502 + r.shortName, e);
9503 serviceDoneExecutingLocked(r, true);
9504 }
9505 }
9506 }
9507 }
9508
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009509 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009510 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009511 System.identityHashCode(r), r.shortName,
9512 (r.app != null) ? r.app.pid : -1);
9513
9514 mServices.remove(r.name);
9515 mServicesByIntent.remove(r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009516 r.totalRestartCount = 0;
9517 unscheduleServiceRestartLocked(r);
9518
9519 // Also make sure it is not on the pending list.
9520 int N = mPendingServices.size();
9521 for (int i=0; i<N; i++) {
9522 if (mPendingServices.get(i) == r) {
9523 mPendingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009524 if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009525 i--;
9526 N--;
9527 }
9528 }
9529
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009530 r.cancelNotification();
9531 r.isForeground = false;
9532 r.foregroundId = 0;
9533 r.foregroundNoti = null;
9534
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009535 // Clear start entries.
Dianne Hackborn39792d22010-08-19 18:01:52 -07009536 r.clearDeliveredStartsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009537 r.pendingStarts.clear();
9538
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009539 if (r.app != null) {
9540 synchronized (r.stats.getBatteryStats()) {
9541 r.stats.stopLaunchedLocked();
9542 }
9543 r.app.services.remove(r);
9544 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009545 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009546 bumpServiceExecutingLocked(r, "stop");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009547 mStoppingServices.add(r);
9548 updateOomAdjLocked(r.app);
9549 r.app.thread.scheduleStopService(r);
9550 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009551 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009552 + r.shortName, e);
9553 serviceDoneExecutingLocked(r, true);
9554 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009555 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009556 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009557 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009558 TAG, "Removed service that has no process: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009559 }
9560 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009561 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009562 TAG, "Removed service that is not running: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009563 }
Vairavan Srinivasana207ce22010-12-23 13:51:48 -08009564
9565 if (r.bindings.size() > 0) {
9566 r.bindings.clear();
9567 }
9568
9569 if (r.restarter instanceof ServiceRestarter) {
9570 ((ServiceRestarter)r.restarter).setService(null);
9571 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009572 }
9573
9574 ComponentName startServiceLocked(IApplicationThread caller,
9575 Intent service, String resolvedType,
9576 int callingPid, int callingUid) {
9577 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009578 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009579 + " type=" + resolvedType + " args=" + service.getExtras());
9580
9581 if (caller != null) {
9582 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9583 if (callerApp == null) {
9584 throw new SecurityException(
9585 "Unable to find app for caller " + caller
9586 + " (pid=" + Binder.getCallingPid()
9587 + ") when starting service " + service);
9588 }
9589 }
9590
9591 ServiceLookupResult res =
9592 retrieveServiceLocked(service, resolvedType,
9593 callingPid, callingUid);
9594 if (res == null) {
9595 return null;
9596 }
9597 if (res.record == null) {
9598 return new ComponentName("!", res.permission != null
9599 ? res.permission : "private to package");
9600 }
9601 ServiceRecord r = res.record;
Dianne Hackborn39792d22010-08-19 18:01:52 -07009602 int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
9603 callingUid, r.packageName, service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009604 if (unscheduleServiceRestartLocked(r)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009605 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009606 }
9607 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009608 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009609 r.lastStartId++;
9610 if (r.lastStartId < 1) {
9611 r.lastStartId = 1;
9612 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009613 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId,
9614 service, targetPermissionUid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009615 r.lastActivity = SystemClock.uptimeMillis();
9616 synchronized (r.stats.getBatteryStats()) {
9617 r.stats.startRunningLocked();
9618 }
9619 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
9620 return new ComponentName("!", "Service process is bad");
9621 }
9622 return r.name;
9623 }
9624 }
9625
9626 public ComponentName startService(IApplicationThread caller, Intent service,
9627 String resolvedType) {
9628 // Refuse possible leaked file descriptors
9629 if (service != null && service.hasFileDescriptors() == true) {
9630 throw new IllegalArgumentException("File descriptors passed in Intent");
9631 }
9632
9633 synchronized(this) {
9634 final int callingPid = Binder.getCallingPid();
9635 final int callingUid = Binder.getCallingUid();
9636 final long origId = Binder.clearCallingIdentity();
9637 ComponentName res = startServiceLocked(caller, service,
9638 resolvedType, callingPid, callingUid);
9639 Binder.restoreCallingIdentity(origId);
9640 return res;
9641 }
9642 }
9643
9644 ComponentName startServiceInPackage(int uid,
9645 Intent service, String resolvedType) {
9646 synchronized(this) {
9647 final long origId = Binder.clearCallingIdentity();
9648 ComponentName res = startServiceLocked(null, service,
9649 resolvedType, -1, uid);
9650 Binder.restoreCallingIdentity(origId);
9651 return res;
9652 }
9653 }
9654
9655 public int stopService(IApplicationThread caller, Intent service,
9656 String resolvedType) {
9657 // Refuse possible leaked file descriptors
9658 if (service != null && service.hasFileDescriptors() == true) {
9659 throw new IllegalArgumentException("File descriptors passed in Intent");
9660 }
9661
9662 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009663 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009664 + " type=" + resolvedType);
9665
9666 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9667 if (caller != null && callerApp == null) {
9668 throw new SecurityException(
9669 "Unable to find app for caller " + caller
9670 + " (pid=" + Binder.getCallingPid()
9671 + ") when stopping service " + service);
9672 }
9673
9674 // If this service is active, make sure it is stopped.
9675 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9676 if (r != null) {
9677 if (r.record != null) {
9678 synchronized (r.record.stats.getBatteryStats()) {
9679 r.record.stats.stopRunningLocked();
9680 }
9681 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009682 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009683 final long origId = Binder.clearCallingIdentity();
9684 bringDownServiceLocked(r.record, false);
9685 Binder.restoreCallingIdentity(origId);
9686 return 1;
9687 }
9688 return -1;
9689 }
9690 }
9691
9692 return 0;
9693 }
9694
9695 public IBinder peekService(Intent service, String resolvedType) {
9696 // Refuse possible leaked file descriptors
9697 if (service != null && service.hasFileDescriptors() == true) {
9698 throw new IllegalArgumentException("File descriptors passed in Intent");
9699 }
9700
9701 IBinder ret = null;
9702
9703 synchronized(this) {
9704 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9705
9706 if (r != null) {
9707 // r.record is null if findServiceLocked() failed the caller permission check
9708 if (r.record == null) {
9709 throw new SecurityException(
9710 "Permission Denial: Accessing service " + r.record.name
9711 + " from pid=" + Binder.getCallingPid()
9712 + ", uid=" + Binder.getCallingUid()
9713 + " requires " + r.permission);
9714 }
9715 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
9716 if (ib != null) {
9717 ret = ib.binder;
9718 }
9719 }
9720 }
9721
9722 return ret;
9723 }
9724
9725 public boolean stopServiceToken(ComponentName className, IBinder token,
9726 int startId) {
9727 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009728 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009729 + " " + token + " startId=" + startId);
9730 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009731 if (r != null) {
9732 if (startId >= 0) {
9733 // Asked to only stop if done with all work. Note that
9734 // to avoid leaks, we will take this as dropping all
9735 // start items up to and including this one.
9736 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9737 if (si != null) {
9738 while (r.deliveredStarts.size() > 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009739 ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
9740 cur.removeUriPermissionsLocked();
9741 if (cur == si) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009742 break;
9743 }
9744 }
9745 }
9746
9747 if (r.lastStartId != startId) {
9748 return false;
9749 }
9750
9751 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009752 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009753 + " is last, but have " + r.deliveredStarts.size()
9754 + " remaining args");
9755 }
9756 }
9757
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009758 synchronized (r.stats.getBatteryStats()) {
9759 r.stats.stopRunningLocked();
9760 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009761 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009762 }
9763 final long origId = Binder.clearCallingIdentity();
9764 bringDownServiceLocked(r, false);
9765 Binder.restoreCallingIdentity(origId);
9766 return true;
9767 }
9768 }
9769 return false;
9770 }
9771
9772 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009773 int id, Notification notification, boolean removeNotification) {
9774 final long origId = Binder.clearCallingIdentity();
9775 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009776 synchronized(this) {
9777 ServiceRecord r = findServiceLocked(className, token);
9778 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009779 if (id != 0) {
9780 if (notification == null) {
9781 throw new IllegalArgumentException("null notification");
9782 }
9783 if (r.foregroundId != id) {
9784 r.cancelNotification();
9785 r.foregroundId = id;
9786 }
9787 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
9788 r.foregroundNoti = notification;
9789 r.isForeground = true;
9790 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009791 if (r.app != null) {
9792 updateServiceForegroundLocked(r.app, true);
9793 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009794 } else {
9795 if (r.isForeground) {
9796 r.isForeground = false;
9797 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07009798 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009799 updateServiceForegroundLocked(r.app, true);
9800 }
9801 }
9802 if (removeNotification) {
9803 r.cancelNotification();
9804 r.foregroundId = 0;
9805 r.foregroundNoti = null;
9806 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009807 }
9808 }
9809 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009810 } finally {
9811 Binder.restoreCallingIdentity(origId);
9812 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009813 }
9814
9815 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
9816 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -07009817 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009818 if (sr.isForeground) {
9819 anyForeground = true;
9820 break;
9821 }
9822 }
9823 if (anyForeground != proc.foregroundServices) {
9824 proc.foregroundServices = anyForeground;
9825 if (oomAdj) {
9826 updateOomAdjLocked();
9827 }
9828 }
9829 }
9830
9831 public int bindService(IApplicationThread caller, IBinder token,
9832 Intent service, String resolvedType,
9833 IServiceConnection connection, int flags) {
9834 // Refuse possible leaked file descriptors
9835 if (service != null && service.hasFileDescriptors() == true) {
9836 throw new IllegalArgumentException("File descriptors passed in Intent");
9837 }
9838
9839 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009840 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009841 + " type=" + resolvedType + " conn=" + connection.asBinder()
9842 + " flags=0x" + Integer.toHexString(flags));
9843 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9844 if (callerApp == null) {
9845 throw new SecurityException(
9846 "Unable to find app for caller " + caller
9847 + " (pid=" + Binder.getCallingPid()
9848 + ") when binding service " + service);
9849 }
9850
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009851 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009852 if (token != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009853 int aindex = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009854 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009855 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009856 return 0;
9857 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009858 activity = (ActivityRecord)mMainStack.mHistory.get(aindex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009859 }
9860
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009861 int clientLabel = 0;
9862 PendingIntent clientIntent = null;
9863
9864 if (callerApp.info.uid == Process.SYSTEM_UID) {
9865 // Hacky kind of thing -- allow system stuff to tell us
9866 // what they are, so we can report this elsewhere for
9867 // others to know why certain services are running.
9868 try {
9869 clientIntent = (PendingIntent)service.getParcelableExtra(
9870 Intent.EXTRA_CLIENT_INTENT);
9871 } catch (RuntimeException e) {
9872 }
9873 if (clientIntent != null) {
9874 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
9875 if (clientLabel != 0) {
9876 // There are no useful extras in the intent, trash them.
9877 // System code calling with this stuff just needs to know
9878 // this will happen.
9879 service = service.cloneFilter();
9880 }
9881 }
9882 }
9883
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009884 ServiceLookupResult res =
9885 retrieveServiceLocked(service, resolvedType,
9886 Binder.getCallingPid(), Binder.getCallingUid());
9887 if (res == null) {
9888 return 0;
9889 }
9890 if (res.record == null) {
9891 return -1;
9892 }
9893 ServiceRecord s = res.record;
9894
9895 final long origId = Binder.clearCallingIdentity();
9896
9897 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009898 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009899 + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009900 }
9901
9902 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
9903 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009904 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009905
9906 IBinder binder = connection.asBinder();
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009907 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9908 if (clist == null) {
9909 clist = new ArrayList<ConnectionRecord>();
9910 s.connections.put(binder, clist);
9911 }
9912 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009913 b.connections.add(c);
9914 if (activity != null) {
9915 if (activity.connections == null) {
9916 activity.connections = new HashSet<ConnectionRecord>();
9917 }
9918 activity.connections.add(c);
9919 }
9920 b.client.connections.add(c);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009921 clist = mServiceConnections.get(binder);
9922 if (clist == null) {
9923 clist = new ArrayList<ConnectionRecord>();
9924 mServiceConnections.put(binder, clist);
9925 }
9926 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009927
9928 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
9929 s.lastActivity = SystemClock.uptimeMillis();
9930 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
9931 return 0;
9932 }
9933 }
9934
9935 if (s.app != null) {
9936 // This could have made the service more important.
9937 updateOomAdjLocked(s.app);
9938 }
9939
Joe Onorato8a9b2202010-02-26 18:56:32 -08009940 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009941 + ": received=" + b.intent.received
9942 + " apps=" + b.intent.apps.size()
9943 + " doRebind=" + b.intent.doRebind);
9944
9945 if (s.app != null && b.intent.received) {
9946 // Service is already running, so we can immediately
9947 // publish the connection.
9948 try {
9949 c.conn.connected(s.name, b.intent.binder);
9950 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009951 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009952 + " to connection " + c.conn.asBinder()
9953 + " (in " + c.binding.client.processName + ")", e);
9954 }
9955
9956 // If this is the first app connected back to this binding,
9957 // and the service had previously asked to be told when
9958 // rebound, then do so.
9959 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
9960 requestServiceBindingLocked(s, b.intent, true);
9961 }
9962 } else if (!b.intent.requested) {
9963 requestServiceBindingLocked(s, b.intent, false);
9964 }
9965
9966 Binder.restoreCallingIdentity(origId);
9967 }
9968
9969 return 1;
9970 }
9971
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009972 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009973 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009974 IBinder binder = c.conn.asBinder();
9975 AppBindRecord b = c.binding;
9976 ServiceRecord s = b.service;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009977 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9978 if (clist != null) {
9979 clist.remove(c);
9980 if (clist.size() == 0) {
9981 s.connections.remove(binder);
9982 }
9983 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009984 b.connections.remove(c);
9985 if (c.activity != null && c.activity != skipAct) {
9986 if (c.activity.connections != null) {
9987 c.activity.connections.remove(c);
9988 }
9989 }
9990 if (b.client != skipApp) {
9991 b.client.connections.remove(c);
9992 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009993 clist = mServiceConnections.get(binder);
9994 if (clist != null) {
9995 clist.remove(c);
9996 if (clist.size() == 0) {
9997 mServiceConnections.remove(binder);
9998 }
9999 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010000
10001 if (b.connections.size() == 0) {
10002 b.intent.apps.remove(b.client);
10003 }
10004
Joe Onorato8a9b2202010-02-26 18:56:32 -080010005 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010006 + ": shouldUnbind=" + b.intent.hasBound);
10007 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
10008 && b.intent.hasBound) {
10009 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010010 bumpServiceExecutingLocked(s, "unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010011 updateOomAdjLocked(s.app);
10012 b.intent.hasBound = false;
10013 // Assume the client doesn't want to know about a rebind;
10014 // we will deal with that later if it asks for one.
10015 b.intent.doRebind = false;
10016 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
10017 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010018 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010019 serviceDoneExecutingLocked(s, true);
10020 }
10021 }
10022
10023 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
10024 bringDownServiceLocked(s, false);
10025 }
10026 }
10027
10028 public boolean unbindService(IServiceConnection connection) {
10029 synchronized (this) {
10030 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010031 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010032 ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
10033 if (clist == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010034 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010035 + connection.asBinder());
10036 return false;
10037 }
10038
10039 final long origId = Binder.clearCallingIdentity();
10040
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010041 while (clist.size() > 0) {
10042 ConnectionRecord r = clist.get(0);
10043 removeConnectionLocked(r, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010044
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010045 if (r.binding.service.app != null) {
10046 // This could have made the service less important.
10047 updateOomAdjLocked(r.binding.service.app);
10048 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010049 }
10050
10051 Binder.restoreCallingIdentity(origId);
10052 }
10053
10054 return true;
10055 }
10056
10057 public void publishService(IBinder token, Intent intent, IBinder service) {
10058 // Refuse possible leaked file descriptors
10059 if (intent != null && intent.hasFileDescriptors() == true) {
10060 throw new IllegalArgumentException("File descriptors passed in Intent");
10061 }
10062
10063 synchronized(this) {
10064 if (!(token instanceof ServiceRecord)) {
10065 throw new IllegalArgumentException("Invalid service token");
10066 }
10067 ServiceRecord r = (ServiceRecord)token;
10068
10069 final long origId = Binder.clearCallingIdentity();
10070
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010071 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010072 + " " + intent + ": " + service);
10073 if (r != null) {
10074 Intent.FilterComparison filter
10075 = new Intent.FilterComparison(intent);
10076 IntentBindRecord b = r.bindings.get(filter);
10077 if (b != null && !b.received) {
10078 b.binder = service;
10079 b.requested = true;
10080 b.received = true;
10081 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010082 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010083 = r.connections.values().iterator();
10084 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010085 ArrayList<ConnectionRecord> clist = it.next();
10086 for (int i=0; i<clist.size(); i++) {
10087 ConnectionRecord c = clist.get(i);
10088 if (!filter.equals(c.binding.intent.intent)) {
10089 if (DEBUG_SERVICE) Slog.v(
10090 TAG, "Not publishing to: " + c);
10091 if (DEBUG_SERVICE) Slog.v(
10092 TAG, "Bound intent: " + c.binding.intent.intent);
10093 if (DEBUG_SERVICE) Slog.v(
10094 TAG, "Published intent: " + intent);
10095 continue;
10096 }
10097 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
10098 try {
10099 c.conn.connected(r.name, service);
10100 } catch (Exception e) {
10101 Slog.w(TAG, "Failure sending service " + r.name +
10102 " to connection " + c.conn.asBinder() +
10103 " (in " + c.binding.client.processName + ")", e);
10104 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010105 }
10106 }
10107 }
10108 }
10109
10110 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
10111
10112 Binder.restoreCallingIdentity(origId);
10113 }
10114 }
10115 }
10116
10117 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
10118 // Refuse possible leaked file descriptors
10119 if (intent != null && intent.hasFileDescriptors() == true) {
10120 throw new IllegalArgumentException("File descriptors passed in Intent");
10121 }
10122
10123 synchronized(this) {
10124 if (!(token instanceof ServiceRecord)) {
10125 throw new IllegalArgumentException("Invalid service token");
10126 }
10127 ServiceRecord r = (ServiceRecord)token;
10128
10129 final long origId = Binder.clearCallingIdentity();
10130
10131 if (r != null) {
10132 Intent.FilterComparison filter
10133 = new Intent.FilterComparison(intent);
10134 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010135 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010136 + " at " + b + ": apps="
10137 + (b != null ? b.apps.size() : 0));
10138 if (b != null) {
10139 if (b.apps.size() > 0) {
10140 // Applications have already bound since the last
10141 // unbind, so just rebind right here.
10142 requestServiceBindingLocked(r, b, true);
10143 } else {
10144 // Note to tell the service the next time there is
10145 // a new client.
10146 b.doRebind = true;
10147 }
10148 }
10149
10150 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
10151
10152 Binder.restoreCallingIdentity(origId);
10153 }
10154 }
10155 }
10156
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010157 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010158 synchronized(this) {
10159 if (!(token instanceof ServiceRecord)) {
10160 throw new IllegalArgumentException("Invalid service token");
10161 }
10162 ServiceRecord r = (ServiceRecord)token;
10163 boolean inStopping = mStoppingServices.contains(token);
10164 if (r != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010165 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010166 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010167 + " with incorrect token: given " + token
10168 + ", expected " + r);
10169 return;
10170 }
10171
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010172 if (type == 1) {
10173 // This is a call from a service start... take care of
10174 // book-keeping.
10175 r.callStart = true;
10176 switch (res) {
10177 case Service.START_STICKY_COMPATIBILITY:
10178 case Service.START_STICKY: {
10179 // We are done with the associated start arguments.
10180 r.findDeliveredStart(startId, true);
10181 // Don't stop if killed.
10182 r.stopIfKilled = false;
10183 break;
10184 }
10185 case Service.START_NOT_STICKY: {
10186 // We are done with the associated start arguments.
10187 r.findDeliveredStart(startId, true);
10188 if (r.lastStartId == startId) {
10189 // There is no more work, and this service
10190 // doesn't want to hang around if killed.
10191 r.stopIfKilled = true;
10192 }
10193 break;
10194 }
10195 case Service.START_REDELIVER_INTENT: {
10196 // We'll keep this item until they explicitly
10197 // call stop for it, but keep track of the fact
10198 // that it was delivered.
10199 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
10200 if (si != null) {
10201 si.deliveryCount = 0;
10202 si.doneExecutingCount++;
10203 // Don't stop if killed.
10204 r.stopIfKilled = true;
10205 }
10206 break;
10207 }
10208 default:
10209 throw new IllegalArgumentException(
10210 "Unknown service start result: " + res);
10211 }
10212 if (res == Service.START_STICKY_COMPATIBILITY) {
10213 r.callStart = false;
10214 }
10215 }
10216
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010217 final long origId = Binder.clearCallingIdentity();
10218 serviceDoneExecutingLocked(r, inStopping);
10219 Binder.restoreCallingIdentity(origId);
10220 } else {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010221 Slog.w(TAG, "Done executing unknown service from pid "
10222 + Binder.getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010223 }
10224 }
10225 }
10226
10227 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010228 if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
10229 + ": nesting=" + r.executeNesting
10230 + ", inStopping=" + inStopping + ", app=" + r.app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070010231 else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010232 r.executeNesting--;
10233 if (r.executeNesting <= 0 && r.app != null) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010234 if (DEBUG_SERVICE) Slog.v(TAG,
10235 "Nesting at 0 of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010236 r.app.executingServices.remove(r);
10237 if (r.app.executingServices.size() == 0) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010238 if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,
10239 "No more executingServices of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010240 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
10241 }
10242 if (inStopping) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010243 if (DEBUG_SERVICE) Slog.v(TAG,
10244 "doneExecuting remove stopping " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010245 mStoppingServices.remove(r);
Mattias Petersson3996b412010-10-27 09:32:51 +020010246 r.bindings.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010247 }
10248 updateOomAdjLocked(r.app);
10249 }
10250 }
10251
10252 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010253 String anrMessage = null;
10254
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010255 synchronized(this) {
10256 if (proc.executingServices.size() == 0 || proc.thread == null) {
10257 return;
10258 }
10259 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
10260 Iterator<ServiceRecord> it = proc.executingServices.iterator();
10261 ServiceRecord timeout = null;
10262 long nextTime = 0;
10263 while (it.hasNext()) {
10264 ServiceRecord sr = it.next();
10265 if (sr.executingStart < maxTime) {
10266 timeout = sr;
10267 break;
10268 }
10269 if (sr.executingStart > nextTime) {
10270 nextTime = sr.executingStart;
10271 }
10272 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010273 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010274 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010275 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010276 } else {
10277 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
10278 msg.obj = proc;
10279 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
10280 }
10281 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010282
10283 if (anrMessage != null) {
10284 appNotResponding(proc, null, null, anrMessage);
10285 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010286 }
10287
10288 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070010289 // BACKUP AND RESTORE
10290 // =========================================================
10291
10292 // Cause the target app to be launched if necessary and its backup agent
10293 // instantiated. The backup agent will invoke backupAgentCreated() on the
10294 // activity manager to announce its creation.
10295 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010296 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070010297 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
10298
10299 synchronized(this) {
10300 // !!! TODO: currently no check here that we're already bound
10301 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
10302 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
10303 synchronized (stats) {
10304 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
10305 }
10306
Dianne Hackborne7f97212011-02-24 14:40:20 -080010307 // Backup agent is now in use, its package can't be stopped.
10308 try {
10309 AppGlobals.getPackageManager().setPackageStoppedState(
10310 app.packageName, false);
10311 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -080010312 } catch (IllegalArgumentException e) {
10313 Slog.w(TAG, "Failed trying to unstop package "
10314 + app.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -080010315 }
10316
Christopher Tate181fafa2009-05-14 11:12:14 -070010317 BackupRecord r = new BackupRecord(ss, app, backupMode);
10318 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
10319 // startProcessLocked() returns existing proc's record if it's already running
10320 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010321 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070010322 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010323 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070010324 return false;
10325 }
10326
10327 r.app = proc;
10328 mBackupTarget = r;
10329 mBackupAppName = app.packageName;
10330
Christopher Tate6fa95972009-06-05 18:43:55 -070010331 // Try not to kill the process during backup
10332 updateOomAdjLocked(proc);
10333
Christopher Tate181fafa2009-05-14 11:12:14 -070010334 // If the process is already attached, schedule the creation of the backup agent now.
10335 // If it is not yet live, this will be done when it attaches to the framework.
10336 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010337 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070010338 try {
10339 proc.thread.scheduleCreateBackupAgent(app, backupMode);
10340 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070010341 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070010342 }
10343 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010344 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070010345 }
10346 // Invariants: at this point, the target app process exists and the application
10347 // is either already running or in the process of coming up. mBackupTarget and
10348 // mBackupAppName describe the app, so that when it binds back to the AM we
10349 // know that it's scheduled for a backup-agent operation.
10350 }
10351
10352 return true;
10353 }
10354
10355 // A backup agent has just come up
10356 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010357 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070010358 + " = " + agent);
10359
10360 synchronized(this) {
10361 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010362 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070010363 return;
10364 }
Dianne Hackborn06740692010-09-22 22:46:21 -070010365 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010366
Dianne Hackborn06740692010-09-22 22:46:21 -070010367 long oldIdent = Binder.clearCallingIdentity();
10368 try {
10369 IBackupManager bm = IBackupManager.Stub.asInterface(
10370 ServiceManager.getService(Context.BACKUP_SERVICE));
10371 bm.agentConnected(agentPackageName, agent);
10372 } catch (RemoteException e) {
10373 // can't happen; the backup manager service is local
10374 } catch (Exception e) {
10375 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
10376 e.printStackTrace();
10377 } finally {
10378 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070010379 }
10380 }
10381
10382 // done with this agent
10383 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010384 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070010385 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010386 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070010387 return;
10388 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010389
10390 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070010391 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010392 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070010393 return;
10394 }
10395
Christopher Tate181fafa2009-05-14 11:12:14 -070010396 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010397 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070010398 return;
10399 }
10400
Christopher Tate6fa95972009-06-05 18:43:55 -070010401 ProcessRecord proc = mBackupTarget.app;
10402 mBackupTarget = null;
10403 mBackupAppName = null;
10404
10405 // Not backing this app up any more; reset its OOM adjustment
10406 updateOomAdjLocked(proc);
10407
Christopher Tatec7b31e32009-06-10 15:49:30 -070010408 // If the app crashed during backup, 'thread' will be null here
10409 if (proc.thread != null) {
10410 try {
10411 proc.thread.scheduleDestroyBackupAgent(appInfo);
10412 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010413 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070010414 e.printStackTrace();
10415 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010416 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010417 }
10418 }
10419 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010420 // BROADCASTS
10421 // =========================================================
10422
Josh Bartel7f208742010-02-25 11:01:44 -060010423 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010424 List cur) {
10425 final ContentResolver resolver = mContext.getContentResolver();
10426 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
10427 if (list == null) {
10428 return cur;
10429 }
10430 int N = list.size();
10431 for (int i=0; i<N; i++) {
10432 Intent intent = list.get(i);
10433 if (filter.match(resolver, intent, true, TAG) >= 0) {
10434 if (cur == null) {
10435 cur = new ArrayList<Intent>();
10436 }
10437 cur.add(intent);
10438 }
10439 }
10440 return cur;
10441 }
10442
10443 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010444 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010445 + mBroadcastsScheduled);
10446
10447 if (mBroadcastsScheduled) {
10448 return;
10449 }
10450 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
10451 mBroadcastsScheduled = true;
10452 }
10453
10454 public Intent registerReceiver(IApplicationThread caller,
10455 IIntentReceiver receiver, IntentFilter filter, String permission) {
10456 synchronized(this) {
10457 ProcessRecord callerApp = null;
10458 if (caller != null) {
10459 callerApp = getRecordForAppLocked(caller);
10460 if (callerApp == null) {
10461 throw new SecurityException(
10462 "Unable to find app for caller " + caller
10463 + " (pid=" + Binder.getCallingPid()
10464 + ") when registering receiver " + receiver);
10465 }
10466 }
10467
10468 List allSticky = null;
10469
10470 // Look for any matching sticky broadcasts...
10471 Iterator actions = filter.actionsIterator();
10472 if (actions != null) {
10473 while (actions.hasNext()) {
10474 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -060010475 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010476 }
10477 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060010478 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010479 }
10480
10481 // The first sticky in the list is returned directly back to
10482 // the client.
10483 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
10484
Joe Onorato8a9b2202010-02-26 18:56:32 -080010485 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010486 + ": " + sticky);
10487
10488 if (receiver == null) {
10489 return sticky;
10490 }
10491
10492 ReceiverList rl
10493 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10494 if (rl == null) {
10495 rl = new ReceiverList(this, callerApp,
10496 Binder.getCallingPid(),
10497 Binder.getCallingUid(), receiver);
10498 if (rl.app != null) {
10499 rl.app.receivers.add(rl);
10500 } else {
10501 try {
10502 receiver.asBinder().linkToDeath(rl, 0);
10503 } catch (RemoteException e) {
10504 return sticky;
10505 }
10506 rl.linkedToDeath = true;
10507 }
10508 mRegisteredReceivers.put(receiver.asBinder(), rl);
10509 }
10510 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
10511 rl.add(bf);
10512 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010513 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010514 }
10515 mReceiverResolver.addFilter(bf);
10516
10517 // Enqueue broadcasts for all existing stickies that match
10518 // this filter.
10519 if (allSticky != null) {
10520 ArrayList receivers = new ArrayList();
10521 receivers.add(bf);
10522
10523 int N = allSticky.size();
10524 for (int i=0; i<N; i++) {
10525 Intent intent = (Intent)allSticky.get(i);
10526 BroadcastRecord r = new BroadcastRecord(intent, null,
10527 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010528 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010529 if (mParallelBroadcasts.size() == 0) {
10530 scheduleBroadcastsLocked();
10531 }
10532 mParallelBroadcasts.add(r);
10533 }
10534 }
10535
10536 return sticky;
10537 }
10538 }
10539
10540 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010541 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010542
10543 boolean doNext = false;
10544
10545 synchronized(this) {
10546 ReceiverList rl
10547 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10548 if (rl != null) {
10549 if (rl.curBroadcast != null) {
10550 BroadcastRecord r = rl.curBroadcast;
10551 doNext = finishReceiverLocked(
10552 receiver.asBinder(), r.resultCode, r.resultData,
10553 r.resultExtras, r.resultAbort, true);
10554 }
10555
10556 if (rl.app != null) {
10557 rl.app.receivers.remove(rl);
10558 }
10559 removeReceiverLocked(rl);
10560 if (rl.linkedToDeath) {
10561 rl.linkedToDeath = false;
10562 rl.receiver.asBinder().unlinkToDeath(rl, 0);
10563 }
10564 }
10565 }
10566
10567 if (!doNext) {
10568 return;
10569 }
10570
10571 final long origId = Binder.clearCallingIdentity();
10572 processNextBroadcast(false);
10573 trimApplications();
10574 Binder.restoreCallingIdentity(origId);
10575 }
10576
10577 void removeReceiverLocked(ReceiverList rl) {
10578 mRegisteredReceivers.remove(rl.receiver.asBinder());
10579 int N = rl.size();
10580 for (int i=0; i<N; i++) {
10581 mReceiverResolver.removeFilter(rl.get(i));
10582 }
10583 }
10584
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010585 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
10586 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
10587 ProcessRecord r = mLruProcesses.get(i);
10588 if (r.thread != null) {
10589 try {
10590 r.thread.dispatchPackageBroadcast(cmd, packages);
10591 } catch (RemoteException ex) {
10592 }
10593 }
10594 }
10595 }
10596
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010597 private final int broadcastIntentLocked(ProcessRecord callerApp,
10598 String callerPackage, Intent intent, String resolvedType,
10599 IIntentReceiver resultTo, int resultCode, String resultData,
10600 Bundle map, String requiredPermission,
10601 boolean ordered, boolean sticky, int callingPid, int callingUid) {
10602 intent = new Intent(intent);
10603
Dianne Hackborne7f97212011-02-24 14:40:20 -080010604 // By default broadcasts do not go to stopped apps.
10605 intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
10606
Joe Onorato8a9b2202010-02-26 18:56:32 -080010607 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010608 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
10609 + " ordered=" + ordered);
10610 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010611 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010612 }
10613
10614 // Handle special intents: if this broadcast is from the package
10615 // manager about a package being removed, we need to remove all of
10616 // its activities from the history stack.
10617 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
10618 intent.getAction());
10619 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
10620 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010621 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010622 || uidRemoved) {
10623 if (checkComponentPermission(
10624 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080010625 callingPid, callingUid, -1, true)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010626 == PackageManager.PERMISSION_GRANTED) {
10627 if (uidRemoved) {
10628 final Bundle intentExtras = intent.getExtras();
10629 final int uid = intentExtras != null
10630 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
10631 if (uid >= 0) {
10632 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
10633 synchronized (bs) {
10634 bs.removeUidStatsLocked(uid);
10635 }
10636 }
10637 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010638 // If resources are unvailble just force stop all
10639 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010640 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010641 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
10642 if (list != null && (list.length > 0)) {
10643 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010644 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010645 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010646 sendPackageBroadcastLocked(
10647 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010648 }
10649 } else {
10650 Uri data = intent.getData();
10651 String ssp;
10652 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
10653 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
10654 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010655 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070010656 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010657 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
10658 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
10659 new String[] {ssp});
10660 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010661 }
10662 }
10663 }
10664 } else {
10665 String msg = "Permission Denial: " + intent.getAction()
10666 + " broadcast from " + callerPackage + " (pid=" + callingPid
10667 + ", uid=" + callingUid + ")"
10668 + " requires "
10669 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010670 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010671 throw new SecurityException(msg);
10672 }
10673 }
10674
10675 /*
10676 * If this is the time zone changed action, queue up a message that will reset the timezone
10677 * of all currently running processes. This message will get queued up before the broadcast
10678 * happens.
10679 */
10680 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
10681 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
10682 }
10683
Robert Greenwalt03595d02010-11-02 14:08:23 -070010684 if (intent.ACTION_CLEAR_DNS_CACHE.equals(intent.getAction())) {
10685 mHandler.sendEmptyMessage(CLEAR_DNS_CACHE);
10686 }
10687
Robert Greenwalt434203a2010-10-11 16:00:27 -070010688 if (Proxy.PROXY_CHANGE_ACTION.equals(intent.getAction())) {
10689 ProxyProperties proxy = intent.getParcelableExtra("proxy");
10690 mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY, proxy));
10691 }
10692
Dianne Hackborn854060af2009-07-09 18:14:31 -070010693 /*
10694 * Prevent non-system code (defined here to be non-persistent
10695 * processes) from sending protected broadcasts.
10696 */
10697 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
10698 || callingUid == Process.SHELL_UID || callingUid == 0) {
10699 // Always okay.
10700 } else if (callerApp == null || !callerApp.persistent) {
10701 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010702 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -070010703 intent.getAction())) {
10704 String msg = "Permission Denial: not allowed to send broadcast "
10705 + intent.getAction() + " from pid="
10706 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010707 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070010708 throw new SecurityException(msg);
10709 }
10710 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010711 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070010712 return BROADCAST_SUCCESS;
10713 }
10714 }
10715
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010716 // Add to the sticky list if requested.
10717 if (sticky) {
10718 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
10719 callingPid, callingUid)
10720 != PackageManager.PERMISSION_GRANTED) {
10721 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
10722 + callingPid + ", uid=" + callingUid
10723 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010724 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010725 throw new SecurityException(msg);
10726 }
10727 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010728 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010729 + " and enforce permission " + requiredPermission);
10730 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
10731 }
10732 if (intent.getComponent() != null) {
10733 throw new SecurityException(
10734 "Sticky broadcasts can't target a specific component");
10735 }
10736 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10737 if (list == null) {
10738 list = new ArrayList<Intent>();
10739 mStickyBroadcasts.put(intent.getAction(), list);
10740 }
10741 int N = list.size();
10742 int i;
10743 for (i=0; i<N; i++) {
10744 if (intent.filterEquals(list.get(i))) {
10745 // This sticky already exists, replace it.
10746 list.set(i, new Intent(intent));
10747 break;
10748 }
10749 }
10750 if (i >= N) {
10751 list.add(new Intent(intent));
10752 }
10753 }
10754
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010755 // Figure out who all will receive this broadcast.
10756 List receivers = null;
10757 List<BroadcastFilter> registeredReceivers = null;
10758 try {
10759 if (intent.getComponent() != null) {
10760 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010761 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070010762 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010763 if (ai != null) {
10764 receivers = new ArrayList();
10765 ResolveInfo ri = new ResolveInfo();
10766 ri.activityInfo = ai;
10767 receivers.add(ri);
10768 }
10769 } else {
10770 // Need to resolve the intent to interested receivers...
10771 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
10772 == 0) {
10773 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010774 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010775 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010776 }
Mihai Preda074edef2009-05-18 17:13:31 +020010777 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010778 }
10779 } catch (RemoteException ex) {
10780 // pm is in same process, this will never happen.
10781 }
10782
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010783 final boolean replacePending =
10784 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
10785
Joe Onorato8a9b2202010-02-26 18:56:32 -080010786 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010787 + " replacePending=" + replacePending);
10788
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010789 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
10790 if (!ordered && NR > 0) {
10791 // If we are not serializing this broadcast, then send the
10792 // registered receivers separately so they don't wait for the
10793 // components to be launched.
10794 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10795 callerPackage, callingPid, callingUid, requiredPermission,
10796 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010797 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010798 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010799 TAG, "Enqueueing parallel broadcast " + r
10800 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010801 boolean replaced = false;
10802 if (replacePending) {
10803 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
10804 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010805 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010806 "***** DROPPING PARALLEL: " + intent);
10807 mParallelBroadcasts.set(i, r);
10808 replaced = true;
10809 break;
10810 }
10811 }
10812 }
10813 if (!replaced) {
10814 mParallelBroadcasts.add(r);
10815 scheduleBroadcastsLocked();
10816 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010817 registeredReceivers = null;
10818 NR = 0;
10819 }
10820
10821 // Merge into one list.
10822 int ir = 0;
10823 if (receivers != null) {
10824 // A special case for PACKAGE_ADDED: do not allow the package
10825 // being added to see this broadcast. This prevents them from
10826 // using this as a back door to get run as soon as they are
10827 // installed. Maybe in the future we want to have a special install
10828 // broadcast or such for apps, but we'd like to deliberately make
10829 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010830 String skipPackages[] = null;
10831 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
10832 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
10833 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
10834 Uri data = intent.getData();
10835 if (data != null) {
10836 String pkgName = data.getSchemeSpecificPart();
10837 if (pkgName != null) {
10838 skipPackages = new String[] { pkgName };
10839 }
10840 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010841 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010842 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070010843 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010844 if (skipPackages != null && (skipPackages.length > 0)) {
10845 for (String skipPackage : skipPackages) {
10846 if (skipPackage != null) {
10847 int NT = receivers.size();
10848 for (int it=0; it<NT; it++) {
10849 ResolveInfo curt = (ResolveInfo)receivers.get(it);
10850 if (curt.activityInfo.packageName.equals(skipPackage)) {
10851 receivers.remove(it);
10852 it--;
10853 NT--;
10854 }
10855 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010856 }
10857 }
10858 }
10859
10860 int NT = receivers != null ? receivers.size() : 0;
10861 int it = 0;
10862 ResolveInfo curt = null;
10863 BroadcastFilter curr = null;
10864 while (it < NT && ir < NR) {
10865 if (curt == null) {
10866 curt = (ResolveInfo)receivers.get(it);
10867 }
10868 if (curr == null) {
10869 curr = registeredReceivers.get(ir);
10870 }
10871 if (curr.getPriority() >= curt.priority) {
10872 // Insert this broadcast record into the final list.
10873 receivers.add(it, curr);
10874 ir++;
10875 curr = null;
10876 it++;
10877 NT++;
10878 } else {
10879 // Skip to the next ResolveInfo in the final list.
10880 it++;
10881 curt = null;
10882 }
10883 }
10884 }
10885 while (ir < NR) {
10886 if (receivers == null) {
10887 receivers = new ArrayList();
10888 }
10889 receivers.add(registeredReceivers.get(ir));
10890 ir++;
10891 }
10892
10893 if ((receivers != null && receivers.size() > 0)
10894 || resultTo != null) {
10895 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10896 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010897 receivers, resultTo, resultCode, resultData, map, ordered,
10898 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010899 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010900 TAG, "Enqueueing ordered broadcast " + r
10901 + ": prev had " + mOrderedBroadcasts.size());
10902 if (DEBUG_BROADCAST) {
10903 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010904 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010905 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010906 boolean replaced = false;
10907 if (replacePending) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010908 for (int i=mOrderedBroadcasts.size()-1; i>0; i--) {
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010909 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010910 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010911 "***** DROPPING ORDERED: " + intent);
10912 mOrderedBroadcasts.set(i, r);
10913 replaced = true;
10914 break;
10915 }
10916 }
10917 }
10918 if (!replaced) {
10919 mOrderedBroadcasts.add(r);
10920 scheduleBroadcastsLocked();
10921 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010922 }
10923
10924 return BROADCAST_SUCCESS;
10925 }
10926
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010927 final Intent verifyBroadcastLocked(Intent intent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010928 // Refuse possible leaked file descriptors
10929 if (intent != null && intent.hasFileDescriptors() == true) {
10930 throw new IllegalArgumentException("File descriptors passed in Intent");
10931 }
10932
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010933 int flags = intent.getFlags();
10934
10935 if (!mProcessesReady) {
10936 // if the caller really truly claims to know what they're doing, go
10937 // ahead and allow the broadcast without launching any receivers
10938 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
10939 intent = new Intent(intent);
10940 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
10941 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
10942 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
10943 + " before boot completion");
10944 throw new IllegalStateException("Cannot broadcast before boot completed");
10945 }
10946 }
10947
10948 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
10949 throw new IllegalArgumentException(
10950 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
10951 }
10952
10953 return intent;
10954 }
10955
10956 public final int broadcastIntent(IApplicationThread caller,
10957 Intent intent, String resolvedType, IIntentReceiver resultTo,
10958 int resultCode, String resultData, Bundle map,
10959 String requiredPermission, boolean serialized, boolean sticky) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010960 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010961 intent = verifyBroadcastLocked(intent);
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010962
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010963 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10964 final int callingPid = Binder.getCallingPid();
10965 final int callingUid = Binder.getCallingUid();
10966 final long origId = Binder.clearCallingIdentity();
10967 int res = broadcastIntentLocked(callerApp,
10968 callerApp != null ? callerApp.info.packageName : null,
10969 intent, resolvedType, resultTo,
10970 resultCode, resultData, map, requiredPermission, serialized,
10971 sticky, callingPid, callingUid);
10972 Binder.restoreCallingIdentity(origId);
10973 return res;
10974 }
10975 }
10976
10977 int broadcastIntentInPackage(String packageName, int uid,
10978 Intent intent, String resolvedType, IIntentReceiver resultTo,
10979 int resultCode, String resultData, Bundle map,
10980 String requiredPermission, boolean serialized, boolean sticky) {
10981 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010982 intent = verifyBroadcastLocked(intent);
10983
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010984 final long origId = Binder.clearCallingIdentity();
10985 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
10986 resultTo, resultCode, resultData, map, requiredPermission,
10987 serialized, sticky, -1, uid);
10988 Binder.restoreCallingIdentity(origId);
10989 return res;
10990 }
10991 }
10992
10993 public final void unbroadcastIntent(IApplicationThread caller,
10994 Intent intent) {
10995 // Refuse possible leaked file descriptors
10996 if (intent != null && intent.hasFileDescriptors() == true) {
10997 throw new IllegalArgumentException("File descriptors passed in Intent");
10998 }
10999
11000 synchronized(this) {
11001 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
11002 != PackageManager.PERMISSION_GRANTED) {
11003 String msg = "Permission Denial: unbroadcastIntent() from pid="
11004 + Binder.getCallingPid()
11005 + ", uid=" + Binder.getCallingUid()
11006 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011007 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011008 throw new SecurityException(msg);
11009 }
11010 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
11011 if (list != null) {
11012 int N = list.size();
11013 int i;
11014 for (i=0; i<N; i++) {
11015 if (intent.filterEquals(list.get(i))) {
11016 list.remove(i);
11017 break;
11018 }
11019 }
11020 }
11021 }
11022 }
11023
11024 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
11025 String resultData, Bundle resultExtras, boolean resultAbort,
11026 boolean explicit) {
11027 if (mOrderedBroadcasts.size() == 0) {
11028 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011029 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011030 }
11031 return false;
11032 }
11033 BroadcastRecord r = mOrderedBroadcasts.get(0);
11034 if (r.receiver == null) {
11035 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011036 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011037 }
11038 return false;
11039 }
11040 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011041 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011042 return false;
11043 }
11044 int state = r.state;
11045 r.state = r.IDLE;
11046 if (state == r.IDLE) {
11047 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011048 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011049 }
11050 }
11051 r.receiver = null;
11052 r.intent.setComponent(null);
11053 if (r.curApp != null) {
11054 r.curApp.curReceiver = null;
11055 }
11056 if (r.curFilter != null) {
11057 r.curFilter.receiverList.curBroadcast = null;
11058 }
11059 r.curFilter = null;
11060 r.curApp = null;
11061 r.curComponent = null;
11062 r.curReceiver = null;
11063 mPendingBroadcast = null;
11064
11065 r.resultCode = resultCode;
11066 r.resultData = resultData;
11067 r.resultExtras = resultExtras;
11068 r.resultAbort = resultAbort;
11069
11070 // We will process the next receiver right now if this is finishing
11071 // an app receiver (which is always asynchronous) or after we have
11072 // come back from calling a receiver.
11073 return state == BroadcastRecord.APP_RECEIVE
11074 || state == BroadcastRecord.CALL_DONE_RECEIVE;
11075 }
11076
11077 public void finishReceiver(IBinder who, int resultCode, String resultData,
11078 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011079 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011080
11081 // Refuse possible leaked file descriptors
11082 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
11083 throw new IllegalArgumentException("File descriptors passed in Bundle");
11084 }
11085
11086 boolean doNext;
11087
11088 final long origId = Binder.clearCallingIdentity();
11089
11090 synchronized(this) {
11091 doNext = finishReceiverLocked(
11092 who, resultCode, resultData, resultExtras, resultAbort, true);
11093 }
11094
11095 if (doNext) {
11096 processNextBroadcast(false);
11097 }
11098 trimApplications();
11099
11100 Binder.restoreCallingIdentity(origId);
11101 }
11102
Jeff Brown4d94a762010-09-23 11:33:28 -070011103 private final void logBroadcastReceiverDiscardLocked(BroadcastRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011104 if (r.nextReceiver > 0) {
11105 Object curReceiver = r.receivers.get(r.nextReceiver-1);
11106 if (curReceiver instanceof BroadcastFilter) {
11107 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080011108 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011109 System.identityHashCode(r),
11110 r.intent.getAction(),
11111 r.nextReceiver - 1,
11112 System.identityHashCode(bf));
11113 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080011114 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011115 System.identityHashCode(r),
11116 r.intent.getAction(),
11117 r.nextReceiver - 1,
11118 ((ResolveInfo)curReceiver).toString());
11119 }
11120 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011121 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011122 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011123 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011124 System.identityHashCode(r),
11125 r.intent.getAction(),
11126 r.nextReceiver,
11127 "NONE");
11128 }
11129 }
11130
Jeff Brown4d94a762010-09-23 11:33:28 -070011131 private final void setBroadcastTimeoutLocked(long timeoutTime) {
11132 if (! mPendingBroadcastTimeoutMessage) {
11133 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
11134 mHandler.sendMessageAtTime(msg, timeoutTime);
11135 mPendingBroadcastTimeoutMessage = true;
11136 }
11137 }
11138
11139 private final void cancelBroadcastTimeoutLocked() {
11140 if (mPendingBroadcastTimeoutMessage) {
11141 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
11142 mPendingBroadcastTimeoutMessage = false;
11143 }
11144 }
11145
11146 private final void broadcastTimeoutLocked(boolean fromMsg) {
11147 if (fromMsg) {
11148 mPendingBroadcastTimeoutMessage = false;
11149 }
11150
11151 if (mOrderedBroadcasts.size() == 0) {
11152 return;
11153 }
11154
11155 long now = SystemClock.uptimeMillis();
11156 BroadcastRecord r = mOrderedBroadcasts.get(0);
11157 if (fromMsg) {
11158 if (mDidDexOpt) {
11159 // Delay timeouts until dexopt finishes.
11160 mDidDexOpt = false;
11161 long timeoutTime = SystemClock.uptimeMillis() + BROADCAST_TIMEOUT;
11162 setBroadcastTimeoutLocked(timeoutTime);
11163 return;
11164 }
11165 if (! mProcessesReady) {
11166 // Only process broadcast timeouts if the system is ready. That way
11167 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
11168 // to do heavy lifting for system up.
11169 return;
11170 }
11171
11172 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
11173 if (timeoutTime > now) {
11174 // We can observe premature timeouts because we do not cancel and reset the
11175 // broadcast timeout message after each receiver finishes. Instead, we set up
11176 // an initial timeout then kick it down the road a little further as needed
11177 // when it expires.
11178 if (DEBUG_BROADCAST) Slog.v(TAG,
11179 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
11180 + timeoutTime);
11181 setBroadcastTimeoutLocked(timeoutTime);
11182 return;
11183 }
11184 }
11185
11186 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver
11187 + ", started " + (now - r.receiverTime) + "ms ago");
11188 r.receiverTime = now;
11189 r.anrCount++;
11190
11191 // Current receiver has passed its expiration date.
11192 if (r.nextReceiver <= 0) {
11193 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
11194 return;
11195 }
11196
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011197 ProcessRecord app = null;
11198 String anrMessage = null;
11199
Jeff Brown4d94a762010-09-23 11:33:28 -070011200 Object curReceiver = r.receivers.get(r.nextReceiver-1);
11201 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
11202 logBroadcastReceiverDiscardLocked(r);
11203 if (curReceiver instanceof BroadcastFilter) {
11204 BroadcastFilter bf = (BroadcastFilter)curReceiver;
11205 if (bf.receiverList.pid != 0
11206 && bf.receiverList.pid != MY_PID) {
11207 synchronized (this.mPidsSelfLocked) {
11208 app = this.mPidsSelfLocked.get(
11209 bf.receiverList.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011210 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011211 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011212 } else {
11213 app = r.curApp;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011214 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011215
Jeff Brown4d94a762010-09-23 11:33:28 -070011216 if (app != null) {
11217 anrMessage = "Broadcast of " + r.intent.toString();
11218 }
11219
11220 if (mPendingBroadcast == r) {
11221 mPendingBroadcast = null;
11222 }
11223
11224 // Move on to the next receiver.
11225 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
11226 r.resultExtras, r.resultAbort, true);
11227 scheduleBroadcastsLocked();
11228
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011229 if (anrMessage != null) {
Jeff Brown4d94a762010-09-23 11:33:28 -070011230 // Post the ANR to the handler since we do not want to process ANRs while
11231 // potentially holding our lock.
11232 mHandler.post(new AppNotResponding(app, anrMessage));
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011233 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011234 }
11235
11236 private final void processCurBroadcastLocked(BroadcastRecord r,
11237 ProcessRecord app) throws RemoteException {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011238 if (DEBUG_BROADCAST) Slog.v(TAG,
11239 "Process cur broadcast " + r + " for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011240 if (app.thread == null) {
11241 throw new RemoteException();
11242 }
11243 r.receiver = app.thread.asBinder();
11244 r.curApp = app;
11245 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011246 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011247
11248 // Tell the application to launch this receiver.
11249 r.intent.setComponent(r.curComponent);
11250
11251 boolean started = false;
11252 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011253 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011254 "Delivering to component " + r.curComponent
11255 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070011256 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011257 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
11258 r.resultCode, r.resultData, r.resultExtras, r.ordered);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011259 if (DEBUG_BROADCAST) Slog.v(TAG,
11260 "Process cur broadcast " + r + " DELIVERED for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011261 started = true;
11262 } finally {
11263 if (!started) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011264 if (DEBUG_BROADCAST) Slog.v(TAG,
11265 "Process cur broadcast " + r + ": NOT STARTED!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011266 r.receiver = null;
11267 r.curApp = null;
11268 app.curReceiver = null;
11269 }
11270 }
11271
11272 }
11273
Jeff Brown4d94a762010-09-23 11:33:28 -070011274 static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011275 Intent intent, int resultCode, String data, Bundle extras,
11276 boolean ordered, boolean sticky) throws RemoteException {
Jeff Brown4d94a762010-09-23 11:33:28 -070011277 // Send the intent to the receiver asynchronously using one-way binder calls.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011278 if (app != null && app.thread != null) {
11279 // If we have an app thread, do the call through that so it is
11280 // correctly ordered with other one-way calls.
11281 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011282 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011283 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011284 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011285 }
11286 }
11287
Jeff Brown4d94a762010-09-23 11:33:28 -070011288 private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011289 BroadcastFilter filter, boolean ordered) {
11290 boolean skip = false;
11291 if (filter.requiredPermission != null) {
11292 int perm = checkComponentPermission(filter.requiredPermission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011293 r.callingPid, r.callingUid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011294 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011295 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011296 + r.intent.toString()
11297 + " from " + r.callerPackage + " (pid="
11298 + r.callingPid + ", uid=" + r.callingUid + ")"
11299 + " requires " + filter.requiredPermission
11300 + " due to registered receiver " + filter);
11301 skip = true;
11302 }
11303 }
11304 if (r.requiredPermission != null) {
11305 int perm = checkComponentPermission(r.requiredPermission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011306 filter.receiverList.pid, filter.receiverList.uid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011307 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011308 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011309 + r.intent.toString()
11310 + " to " + filter.receiverList.app
11311 + " (pid=" + filter.receiverList.pid
11312 + ", uid=" + filter.receiverList.uid + ")"
11313 + " requires " + r.requiredPermission
11314 + " due to sender " + r.callerPackage
11315 + " (uid " + r.callingUid + ")");
11316 skip = true;
11317 }
11318 }
11319
11320 if (!skip) {
11321 // If this is not being sent as an ordered broadcast, then we
11322 // don't want to touch the fields that keep track of the current
11323 // state of ordered broadcasts.
11324 if (ordered) {
11325 r.receiver = filter.receiverList.receiver.asBinder();
11326 r.curFilter = filter;
11327 filter.receiverList.curBroadcast = r;
11328 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011329 if (filter.receiverList.app != null) {
11330 // Bump hosting application to no longer be in background
11331 // scheduling class. Note that we can't do that if there
11332 // isn't an app... but we can only be in that case for
11333 // things that directly call the IActivityManager API, which
11334 // are already core system stuff so don't matter for this.
11335 r.curApp = filter.receiverList.app;
11336 filter.receiverList.app.curReceiver = r;
11337 updateOomAdjLocked();
11338 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011339 }
11340 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011341 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011342 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011343 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011344 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011345 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011346 performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011347 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011348 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011349 if (ordered) {
11350 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
11351 }
11352 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011353 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011354 if (ordered) {
11355 r.receiver = null;
11356 r.curFilter = null;
11357 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011358 if (filter.receiverList.app != null) {
11359 filter.receiverList.app.curReceiver = null;
11360 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011361 }
11362 }
11363 }
11364 }
11365
Dianne Hackborn12527f92009-11-11 17:39:50 -080011366 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
11367 if (r.callingUid < 0) {
11368 // This was from a registerReceiver() call; ignore it.
11369 return;
11370 }
11371 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
11372 MAX_BROADCAST_HISTORY-1);
11373 r.finishTime = SystemClock.uptimeMillis();
11374 mBroadcastHistory[0] = r;
11375 }
11376
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011377 private final void processNextBroadcast(boolean fromMsg) {
11378 synchronized(this) {
11379 BroadcastRecord r;
11380
Joe Onorato8a9b2202010-02-26 18:56:32 -080011381 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011382 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011383 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011384
11385 updateCpuStats();
11386
11387 if (fromMsg) {
11388 mBroadcastsScheduled = false;
11389 }
11390
11391 // First, deliver any non-serialized broadcasts right away.
11392 while (mParallelBroadcasts.size() > 0) {
11393 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080011394 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011395 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011396 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011397 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011398 for (int i=0; i<N; i++) {
11399 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011400 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011401 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011402 + target + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011403 deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011404 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080011405 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011406 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011407 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011408 }
11409
11410 // Now take care of the next serialized one...
11411
11412 // If we are waiting for a process to come up to handle the next
11413 // broadcast, then do nothing at this point. Just in case, we
11414 // check that the process we're waiting for still exists.
11415 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070011416 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011417 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070011418 + mPendingBroadcast.curApp);
11419 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011420
11421 boolean isDead;
11422 synchronized (mPidsSelfLocked) {
11423 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
11424 }
11425 if (!isDead) {
11426 // It's still alive, so keep waiting
11427 return;
11428 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011429 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011430 + " died before responding to broadcast");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011431 mPendingBroadcast.state = BroadcastRecord.IDLE;
11432 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011433 mPendingBroadcast = null;
11434 }
11435 }
11436
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011437 boolean looped = false;
11438
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011439 do {
11440 if (mOrderedBroadcasts.size() == 0) {
11441 // No more broadcasts pending, so all done!
11442 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011443 if (looped) {
11444 // If we had finished the last ordered broadcast, then
11445 // make sure all processes have correct oom and sched
11446 // adjustments.
11447 updateOomAdjLocked();
11448 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011449 return;
11450 }
11451 r = mOrderedBroadcasts.get(0);
11452 boolean forceReceive = false;
11453
11454 // Ensure that even if something goes awry with the timeout
11455 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011456 // and continue to make progress.
11457 //
11458 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
Jeff Brown4d94a762010-09-23 11:33:28 -070011459 // receivers don't get executed with timeouts. They're intended for
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011460 // one time heavy lifting after system upgrades and can take
11461 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011462 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011463 if (mProcessesReady && r.dispatchTime > 0) {
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011464 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011465 if ((numReceivers > 0) &&
11466 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011467 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011468 + " now=" + now
11469 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080011470 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011471 + " intent=" + r.intent
11472 + " numReceivers=" + numReceivers
11473 + " nextReceiver=" + r.nextReceiver
11474 + " state=" + r.state);
Jeff Brown4d94a762010-09-23 11:33:28 -070011475 broadcastTimeoutLocked(false); // forcibly finish this broadcast
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011476 forceReceive = true;
11477 r.state = BroadcastRecord.IDLE;
11478 }
11479 }
11480
11481 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011482 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011483 "processNextBroadcast() called when not idle (state="
11484 + r.state + ")");
11485 return;
11486 }
11487
11488 if (r.receivers == null || r.nextReceiver >= numReceivers
11489 || r.resultAbort || forceReceive) {
11490 // No more receivers for this broadcast! Send the final
11491 // result if requested...
11492 if (r.resultTo != null) {
11493 try {
11494 if (DEBUG_BROADCAST) {
11495 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011496 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011497 + " seq=" + seq + " app=" + r.callerApp);
11498 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011499 performReceiveLocked(r.callerApp, r.resultTo,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011500 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011501 r.resultData, r.resultExtras, false, false);
Johannes Carlssonb5a86542010-10-27 10:08:10 +020011502 // Set this to null so that the reference
11503 // (local and remote) isnt kept in the mBroadcastHistory.
11504 r.resultTo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011505 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011506 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011507 }
11508 }
11509
Joe Onorato8a9b2202010-02-26 18:56:32 -080011510 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
Jeff Brown4d94a762010-09-23 11:33:28 -070011511 cancelBroadcastTimeoutLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011512
Joe Onorato8a9b2202010-02-26 18:56:32 -080011513 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011514 + r);
11515
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011516 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080011517 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011518 mOrderedBroadcasts.remove(0);
11519 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011520 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011521 continue;
11522 }
11523 } while (r == null);
11524
11525 // Get the next receiver...
11526 int recIdx = r.nextReceiver++;
11527
11528 // Keep track of when this receiver started, and make sure there
11529 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080011530 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011531 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080011532 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011533
Joe Onorato8a9b2202010-02-26 18:56:32 -080011534 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011535 + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011536 }
11537 if (! mPendingBroadcastTimeoutMessage) {
11538 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011539 if (DEBUG_BROADCAST) Slog.v(TAG,
Jeff Brown4d94a762010-09-23 11:33:28 -070011540 "Submitting BROADCAST_TIMEOUT_MSG for " + r + " at " + timeoutTime);
11541 setBroadcastTimeoutLocked(timeoutTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011542 }
11543
11544 Object nextReceiver = r.receivers.get(recIdx);
11545 if (nextReceiver instanceof BroadcastFilter) {
11546 // Simple case: this is a registered receiver who gets
11547 // a direct call.
11548 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011549 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011550 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011551 + filter + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011552 deliverToRegisteredReceiverLocked(r, filter, r.ordered);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011553 if (r.receiver == null || !r.ordered) {
11554 // The receiver has already finished, so schedule to
11555 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011556 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
11557 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011558 r.state = BroadcastRecord.IDLE;
11559 scheduleBroadcastsLocked();
11560 }
11561 return;
11562 }
11563
11564 // Hard case: need to instantiate the receiver, possibly
11565 // starting its application process to host it.
11566
11567 ResolveInfo info =
11568 (ResolveInfo)nextReceiver;
11569
11570 boolean skip = false;
11571 int perm = checkComponentPermission(info.activityInfo.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011572 r.callingPid, r.callingUid, info.activityInfo.applicationInfo.uid,
11573 info.activityInfo.exported);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011574 if (perm != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011575 if (!info.activityInfo.exported) {
11576 Slog.w(TAG, "Permission Denial: broadcasting "
11577 + r.intent.toString()
11578 + " from " + r.callerPackage + " (pid=" + r.callingPid
11579 + ", uid=" + r.callingUid + ")"
11580 + " is not exported from uid " + info.activityInfo.applicationInfo.uid
11581 + " due to receiver " + info.activityInfo.packageName
11582 + "/" + info.activityInfo.name);
11583 } else {
11584 Slog.w(TAG, "Permission Denial: broadcasting "
11585 + r.intent.toString()
11586 + " from " + r.callerPackage + " (pid=" + r.callingPid
11587 + ", uid=" + r.callingUid + ")"
11588 + " requires " + info.activityInfo.permission
11589 + " due to receiver " + info.activityInfo.packageName
11590 + "/" + info.activityInfo.name);
11591 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011592 skip = true;
11593 }
11594 if (r.callingUid != Process.SYSTEM_UID &&
11595 r.requiredPermission != null) {
11596 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011597 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011598 checkPermission(r.requiredPermission,
11599 info.activityInfo.applicationInfo.packageName);
11600 } catch (RemoteException e) {
11601 perm = PackageManager.PERMISSION_DENIED;
11602 }
11603 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011604 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011605 + r.intent + " to "
11606 + info.activityInfo.applicationInfo.packageName
11607 + " requires " + r.requiredPermission
11608 + " due to sender " + r.callerPackage
11609 + " (uid " + r.callingUid + ")");
11610 skip = true;
11611 }
11612 }
11613 if (r.curApp != null && r.curApp.crashing) {
11614 // If the target process is crashing, just skip it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011615 if (DEBUG_BROADCAST) Slog.v(TAG,
11616 "Skipping deliver ordered " + r + " to " + r.curApp
11617 + ": process crashing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011618 skip = true;
11619 }
11620
11621 if (skip) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011622 if (DEBUG_BROADCAST) Slog.v(TAG,
11623 "Skipping delivery of ordered " + r + " for whatever reason");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011624 r.receiver = null;
11625 r.curFilter = null;
11626 r.state = BroadcastRecord.IDLE;
11627 scheduleBroadcastsLocked();
11628 return;
11629 }
11630
11631 r.state = BroadcastRecord.APP_RECEIVE;
11632 String targetProcess = info.activityInfo.processName;
11633 r.curComponent = new ComponentName(
11634 info.activityInfo.applicationInfo.packageName,
11635 info.activityInfo.name);
11636 r.curReceiver = info.activityInfo;
11637
Dianne Hackborne7f97212011-02-24 14:40:20 -080011638 // Broadcast is being executed, its package can't be stopped.
11639 try {
11640 AppGlobals.getPackageManager().setPackageStoppedState(
11641 r.curComponent.getPackageName(), false);
11642 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -080011643 } catch (IllegalArgumentException e) {
11644 Slog.w(TAG, "Failed trying to unstop package "
11645 + r.curComponent.getPackageName() + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -080011646 }
11647
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011648 // Is this receiver's application already running?
11649 ProcessRecord app = getProcessRecordLocked(targetProcess,
11650 info.activityInfo.applicationInfo.uid);
11651 if (app != null && app.thread != null) {
11652 try {
11653 processCurBroadcastLocked(r, app);
11654 return;
11655 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011656 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011657 + r.curComponent, e);
11658 }
11659
11660 // If a dead object exception was thrown -- fall through to
11661 // restart the application.
11662 }
11663
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011664 // Not running -- get it started, to be executed when the app comes up.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011665 if (DEBUG_BROADCAST) Slog.v(TAG,
11666 "Need to start app " + targetProcess + " for broadcast " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011667 if ((r.curApp=startProcessLocked(targetProcess,
11668 info.activityInfo.applicationInfo, true,
11669 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011670 "broadcast", r.curComponent,
11671 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
11672 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011673 // Ah, this recipient is unavailable. Finish it if necessary,
11674 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011675 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011676 + info.activityInfo.applicationInfo.packageName + "/"
11677 + info.activityInfo.applicationInfo.uid + " for broadcast "
11678 + r.intent + ": process is bad");
Jeff Brown4d94a762010-09-23 11:33:28 -070011679 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011680 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
11681 r.resultExtras, r.resultAbort, true);
11682 scheduleBroadcastsLocked();
11683 r.state = BroadcastRecord.IDLE;
11684 return;
11685 }
11686
11687 mPendingBroadcast = r;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011688 mPendingBroadcastRecvIndex = recIdx;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011689 }
11690 }
11691
11692 // =========================================================
11693 // INSTRUMENTATION
11694 // =========================================================
11695
11696 public boolean startInstrumentation(ComponentName className,
11697 String profileFile, int flags, Bundle arguments,
11698 IInstrumentationWatcher watcher) {
11699 // Refuse possible leaked file descriptors
11700 if (arguments != null && arguments.hasFileDescriptors()) {
11701 throw new IllegalArgumentException("File descriptors passed in Bundle");
11702 }
11703
11704 synchronized(this) {
11705 InstrumentationInfo ii = null;
11706 ApplicationInfo ai = null;
11707 try {
11708 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011709 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011710 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011711 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011712 } catch (PackageManager.NameNotFoundException e) {
11713 }
11714 if (ii == null) {
11715 reportStartInstrumentationFailure(watcher, className,
11716 "Unable to find instrumentation info for: " + className);
11717 return false;
11718 }
11719 if (ai == null) {
11720 reportStartInstrumentationFailure(watcher, className,
11721 "Unable to find instrumentation target package: " + ii.targetPackage);
11722 return false;
11723 }
11724
11725 int match = mContext.getPackageManager().checkSignatures(
11726 ii.targetPackage, ii.packageName);
11727 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
11728 String msg = "Permission Denial: starting instrumentation "
11729 + className + " from pid="
11730 + Binder.getCallingPid()
11731 + ", uid=" + Binder.getCallingPid()
11732 + " not allowed because package " + ii.packageName
11733 + " does not have a signature matching the target "
11734 + ii.targetPackage;
11735 reportStartInstrumentationFailure(watcher, className, msg);
11736 throw new SecurityException(msg);
11737 }
11738
11739 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011740 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011741 ProcessRecord app = addAppLocked(ai);
11742 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070011743 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011744 app.instrumentationProfileFile = profileFile;
11745 app.instrumentationArguments = arguments;
11746 app.instrumentationWatcher = watcher;
11747 app.instrumentationResultClass = className;
11748 Binder.restoreCallingIdentity(origId);
11749 }
11750
11751 return true;
11752 }
11753
11754 /**
11755 * Report errors that occur while attempting to start Instrumentation. Always writes the
11756 * error to the logs, but if somebody is watching, send the report there too. This enables
11757 * the "am" command to report errors with more information.
11758 *
11759 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
11760 * @param cn The component name of the instrumentation.
11761 * @param report The error report.
11762 */
11763 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
11764 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011765 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011766 try {
11767 if (watcher != null) {
11768 Bundle results = new Bundle();
11769 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
11770 results.putString("Error", report);
11771 watcher.instrumentationStatus(cn, -1, results);
11772 }
11773 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011774 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011775 }
11776 }
11777
11778 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
11779 if (app.instrumentationWatcher != null) {
11780 try {
11781 // NOTE: IInstrumentationWatcher *must* be oneway here
11782 app.instrumentationWatcher.instrumentationFinished(
11783 app.instrumentationClass,
11784 resultCode,
11785 results);
11786 } catch (RemoteException e) {
11787 }
11788 }
11789 app.instrumentationWatcher = null;
11790 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070011791 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011792 app.instrumentationProfileFile = null;
11793 app.instrumentationArguments = null;
11794
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011795 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011796 }
11797
11798 public void finishInstrumentation(IApplicationThread target,
11799 int resultCode, Bundle results) {
11800 // Refuse possible leaked file descriptors
11801 if (results != null && results.hasFileDescriptors()) {
11802 throw new IllegalArgumentException("File descriptors passed in Intent");
11803 }
11804
11805 synchronized(this) {
11806 ProcessRecord app = getRecordForAppLocked(target);
11807 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011808 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011809 return;
11810 }
11811 final long origId = Binder.clearCallingIdentity();
11812 finishInstrumentationLocked(app, resultCode, results);
11813 Binder.restoreCallingIdentity(origId);
11814 }
11815 }
11816
11817 // =========================================================
11818 // CONFIGURATION
11819 // =========================================================
11820
11821 public ConfigurationInfo getDeviceConfigurationInfo() {
11822 ConfigurationInfo config = new ConfigurationInfo();
11823 synchronized (this) {
11824 config.reqTouchScreen = mConfiguration.touchscreen;
11825 config.reqKeyboardType = mConfiguration.keyboard;
11826 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070011827 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
11828 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011829 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
11830 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070011831 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
11832 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011833 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
11834 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070011835 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011836 }
11837 return config;
11838 }
11839
11840 public Configuration getConfiguration() {
11841 Configuration ci;
11842 synchronized(this) {
11843 ci = new Configuration(mConfiguration);
11844 }
11845 return ci;
11846 }
11847
11848 public void updateConfiguration(Configuration values) {
11849 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
11850 "updateConfiguration()");
11851
11852 synchronized(this) {
11853 if (values == null && mWindowManager != null) {
11854 // sentinel: fetch the current configuration from the window manager
11855 values = mWindowManager.computeNewConfiguration();
11856 }
11857
11858 final long origId = Binder.clearCallingIdentity();
11859 updateConfigurationLocked(values, null);
11860 Binder.restoreCallingIdentity(origId);
11861 }
11862 }
11863
11864 /**
11865 * Do either or both things: (1) change the current configuration, and (2)
11866 * make sure the given activity is running with the (now) current
11867 * configuration. Returns true if the activity has been left running, or
11868 * false if <var>starting</var> is being destroyed to match the new
11869 * configuration.
11870 */
11871 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011872 ActivityRecord starting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011873 int changes = 0;
11874
11875 boolean kept = true;
11876
11877 if (values != null) {
11878 Configuration newConfig = new Configuration(mConfiguration);
11879 changes = newConfig.updateFrom(values);
11880 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011881 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011882 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011883 }
11884
Doug Zongker2bec3d42009-12-04 12:52:44 -080011885 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011886
11887 if (values.locale != null) {
11888 saveLocaleLocked(values.locale,
11889 !values.locale.equals(mConfiguration.locale),
11890 values.userSetLocale);
11891 }
11892
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011893 mConfigurationSeq++;
11894 if (mConfigurationSeq <= 0) {
11895 mConfigurationSeq = 1;
11896 }
11897 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011898 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011899 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080011900
11901 AttributeCache ac = AttributeCache.instance();
11902 if (ac != null) {
11903 ac.updateConfiguration(mConfiguration);
11904 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011905
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080011906 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
11907 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
11908 msg.obj = new Configuration(mConfiguration);
11909 mHandler.sendMessage(msg);
11910 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011911
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011912 for (int i=mLruProcesses.size()-1; i>=0; i--) {
11913 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011914 try {
11915 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011916 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011917 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011918 app.thread.scheduleConfigurationChanged(mConfiguration);
11919 }
11920 } catch (Exception e) {
11921 }
11922 }
11923 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011924 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
11925 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011926 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
11927 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080011928 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
11929 broadcastIntentLocked(null, null,
11930 new Intent(Intent.ACTION_LOCALE_CHANGED),
11931 null, null, 0, null, null,
11932 null, false, false, MY_PID, Process.SYSTEM_UID);
11933 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011934 }
11935 }
11936
11937 if (changes != 0 && starting == null) {
11938 // If the configuration changed, and the caller is not already
11939 // in the process of starting an activity, then find the top
11940 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011941 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011942 }
11943
11944 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011945 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
Dianne Hackborn5f4d6432010-12-21 20:40:11 -080011946 // And we need to make sure at this point that all other activities
11947 // are made visible with the correct configuration.
11948 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011949 }
11950
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011951 if (values != null && mWindowManager != null) {
11952 mWindowManager.setNewConfiguration(mConfiguration);
11953 }
11954
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011955 return kept;
11956 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011957
11958 /**
11959 * Save the locale. You must be inside a synchronized (this) block.
11960 */
11961 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
11962 if(isDiff) {
11963 SystemProperties.set("user.language", l.getLanguage());
11964 SystemProperties.set("user.region", l.getCountry());
11965 }
11966
11967 if(isPersist) {
11968 SystemProperties.set("persist.sys.language", l.getLanguage());
11969 SystemProperties.set("persist.sys.country", l.getCountry());
11970 SystemProperties.set("persist.sys.localevar", l.getVariant());
11971 }
11972 }
11973
11974 // =========================================================
11975 // LIFETIME MANAGEMENT
11976 // =========================================================
11977
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011978 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
11979 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011980 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011981 // This adjustment has already been computed. If we are calling
11982 // from the top, we may have already computed our adjustment with
11983 // an earlier hidden adjustment that isn't really for us... if
11984 // so, use the new hidden adjustment.
11985 if (!recursed && app.hidden) {
11986 app.curAdj = hiddenAdj;
11987 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011988 return app.curAdj;
11989 }
11990
11991 if (app.thread == null) {
11992 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011993 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011994 return (app.curAdj=EMPTY_APP_ADJ);
11995 }
11996
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011997 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
11998 // The max adjustment doesn't allow this app to be anything
11999 // below foreground, so it is not worth doing work for it.
12000 app.adjType = "fixed";
12001 app.adjSeq = mAdjSeq;
12002 app.curRawAdj = app.maxAdj;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012003 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012004 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
12005 return (app.curAdj=app.maxAdj);
12006 }
12007
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012008 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012009 app.adjSource = null;
12010 app.adjTarget = null;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012011 app.keeping = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012012 app.empty = false;
12013 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012014
The Android Open Source Project4df24232009-03-05 14:34:35 -080012015 // Determine the importance of the process, starting with most
12016 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012017 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012018 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012019 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012020 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012021 // The last app on the list is the foreground app.
12022 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012023 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012024 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012025 } else if (app.instrumentationClass != null) {
12026 // Don't want to kill running instrumentation.
12027 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012028 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012029 app.adjType = "instrumentation";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012030 } else if (app.curReceiver != null ||
12031 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
12032 // An app that is currently receiving a broadcast also
12033 // counts as being in the foreground.
12034 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012035 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012036 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012037 } else if (app.executingServices.size() > 0) {
12038 // An app that is currently executing a service callback also
12039 // counts as being in the foreground.
12040 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012041 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012042 app.adjType = "exec-service";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012043 } else if ((N=app.activities.size()) != 0) {
12044 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012045 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012046 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012047 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012048 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012049 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012050 for (int j=0; j<N; j++) {
Dianne Hackborn0aae2d42010-12-07 23:51:29 -080012051 ActivityRecord r = app.activities.get(j);
12052 if (r.visible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012053 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012054 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012055 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012056 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012057 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012058 break;
Dianne Hackborn0aae2d42010-12-07 23:51:29 -080012059 } else if (r.state == ActivityState.PAUSING
12060 || r.state == ActivityState.PAUSED
12061 || r.state == ActivityState.STOPPING) {
12062 adj = PERCEPTIBLE_APP_ADJ;
12063 app.adjType = "stopping";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012064 }
12065 }
12066 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012067 // A very not-needed process. If this is lower in the lru list,
12068 // we will push it in to the empty bucket.
12069 app.hidden = true;
12070 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012071 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012072 adj = hiddenAdj;
12073 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012074 }
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012075
12076 if (adj > PERCEPTIBLE_APP_ADJ) {
12077 if (app.foregroundServices) {
12078 // The user is aware of this app, so make it visible.
12079 adj = PERCEPTIBLE_APP_ADJ;
12080 schedGroup = Process.THREAD_GROUP_DEFAULT;
12081 app.adjType = "foreground-service";
12082 } else if (app.forcingToForeground != null) {
12083 // The user is aware of this app, so make it visible.
12084 adj = PERCEPTIBLE_APP_ADJ;
12085 schedGroup = Process.THREAD_GROUP_DEFAULT;
12086 app.adjType = "force-foreground";
12087 app.adjSource = app.forcingToForeground;
12088 }
12089 }
12090
12091 if (adj > HEAVY_WEIGHT_APP_ADJ && app == mHeavyWeightProcess) {
12092 // We don't want to kill the current heavy-weight process.
12093 adj = HEAVY_WEIGHT_APP_ADJ;
12094 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
12095 app.adjType = "heavy";
12096 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012097
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012098 if (adj > HOME_APP_ADJ && app == mHomeProcess) {
12099 // This process is hosting what we currently consider to be the
12100 // home app, so we don't want to let it go into the background.
12101 adj = HOME_APP_ADJ;
12102 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
12103 app.adjType = "home";
12104 }
12105
Joe Onorato8a9b2202010-02-26 18:56:32 -080012106 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012107
The Android Open Source Project4df24232009-03-05 14:34:35 -080012108 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012109 // there are applications dependent on our services or providers, but
12110 // this gives us a baseline and makes sure we don't get into an
12111 // infinite recursion.
12112 app.adjSeq = mAdjSeq;
12113 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012114
Christopher Tate6fa95972009-06-05 18:43:55 -070012115 if (mBackupTarget != null && app == mBackupTarget.app) {
12116 // If possible we want to avoid killing apps while they're being backed up
12117 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012118 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070012119 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012120 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012121 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070012122 }
12123 }
12124
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012125 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
12126 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012127 final long now = SystemClock.uptimeMillis();
12128 // This process is more important if the top activity is
12129 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070012130 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012131 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012132 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012133 if (s.startRequested) {
12134 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
12135 // This service has seen some activity within
12136 // recent memory, so we will keep its process ahead
12137 // of the background processes.
12138 if (adj > SECONDARY_SERVER_ADJ) {
12139 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012140 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012141 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012142 }
12143 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012144 // If we have let the service slide into the background
12145 // state, still have some text describing what it is doing
12146 // even though the service no longer has an impact.
12147 if (adj > SECONDARY_SERVER_ADJ) {
12148 app.adjType = "started-bg-services";
12149 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012150 // Don't kill this process because it is doing work; it
12151 // has said it is doing work.
12152 app.keeping = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012153 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012154 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
12155 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012156 Iterator<ArrayList<ConnectionRecord>> kt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012157 = s.connections.values().iterator();
12158 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012159 ArrayList<ConnectionRecord> clist = kt.next();
12160 for (int i=0; i<clist.size() && adj > FOREGROUND_APP_ADJ; i++) {
12161 // XXX should compute this based on the max of
12162 // all connected clients.
12163 ConnectionRecord cr = clist.get(i);
12164 if (cr.binding.client == app) {
12165 // Binding to ourself is not interesting.
12166 continue;
12167 }
12168 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
12169 ProcessRecord client = cr.binding.client;
12170 int myHiddenAdj = hiddenAdj;
12171 if (myHiddenAdj > client.hiddenAdj) {
12172 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
12173 myHiddenAdj = client.hiddenAdj;
12174 } else {
12175 myHiddenAdj = VISIBLE_APP_ADJ;
12176 }
12177 }
12178 int clientAdj = computeOomAdjLocked(
12179 client, myHiddenAdj, TOP_APP, true);
12180 if (adj > clientAdj) {
12181 adj = clientAdj >= VISIBLE_APP_ADJ
12182 ? clientAdj : VISIBLE_APP_ADJ;
12183 if (!client.hidden) {
12184 app.hidden = false;
12185 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012186 if (client.keeping) {
12187 app.keeping = true;
12188 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012189 app.adjType = "service";
12190 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12191 .REASON_SERVICE_IN_USE;
12192 app.adjSource = cr.binding.client;
12193 app.adjTarget = s.name;
12194 }
12195 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
12196 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
12197 schedGroup = Process.THREAD_GROUP_DEFAULT;
12198 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012199 }
12200 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012201 ActivityRecord a = cr.activity;
12202 //if (a != null) {
12203 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
12204 //}
12205 if (a != null && adj > FOREGROUND_APP_ADJ &&
12206 (a.state == ActivityState.RESUMED
12207 || a.state == ActivityState.PAUSING)) {
12208 adj = FOREGROUND_APP_ADJ;
12209 schedGroup = Process.THREAD_GROUP_DEFAULT;
12210 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012211 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012212 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12213 .REASON_SERVICE_IN_USE;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012214 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012215 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012216 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012217 }
12218 }
12219 }
12220 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012221
Dianne Hackborn287952c2010-09-22 22:34:31 -070012222 // Finally, if this process has active services running in it, we
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012223 // would like to avoid killing it unless it would prevent the current
12224 // application from running. By default we put the process in
12225 // with the rest of the background processes; as we scan through
12226 // its services we may bump it up from there.
12227 if (adj > hiddenAdj) {
12228 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012229 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012230 app.adjType = "bg-services";
12231 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012232 }
12233
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012234 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
12235 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012236 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012237 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
12238 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012239 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012240 if (cpr.clients.size() != 0) {
12241 Iterator<ProcessRecord> kt = cpr.clients.iterator();
12242 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
12243 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070012244 if (client == app) {
12245 // Being our own client is not interesting.
12246 continue;
12247 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012248 int myHiddenAdj = hiddenAdj;
12249 if (myHiddenAdj > client.hiddenAdj) {
12250 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
12251 myHiddenAdj = client.hiddenAdj;
12252 } else {
12253 myHiddenAdj = FOREGROUND_APP_ADJ;
12254 }
12255 }
12256 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012257 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012258 if (adj > clientAdj) {
12259 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012260 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012261 if (!client.hidden) {
12262 app.hidden = false;
12263 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012264 if (client.keeping) {
12265 app.keeping = true;
12266 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012267 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012268 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12269 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012270 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012271 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012272 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012273 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
12274 schedGroup = Process.THREAD_GROUP_DEFAULT;
12275 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012276 }
12277 }
12278 // If the provider has external (non-framework) process
12279 // dependencies, ensure that its adjustment is at least
12280 // FOREGROUND_APP_ADJ.
12281 if (cpr.externals != 0) {
12282 if (adj > FOREGROUND_APP_ADJ) {
12283 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012284 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012285 app.hidden = false;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012286 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012287 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012288 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012289 }
12290 }
12291 }
12292 }
12293
12294 app.curRawAdj = adj;
12295
Joe Onorato8a9b2202010-02-26 18:56:32 -080012296 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012297 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
12298 if (adj > app.maxAdj) {
12299 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070012300 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012301 schedGroup = Process.THREAD_GROUP_DEFAULT;
12302 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012303 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012304 if (adj < HIDDEN_APP_MIN_ADJ) {
12305 app.keeping = true;
12306 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012307
12308 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012309 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012310
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012311 return adj;
12312 }
12313
12314 /**
12315 * Ask a given process to GC right now.
12316 */
12317 final void performAppGcLocked(ProcessRecord app) {
12318 try {
12319 app.lastRequestedGc = SystemClock.uptimeMillis();
12320 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012321 if (app.reportLowMemory) {
12322 app.reportLowMemory = false;
12323 app.thread.scheduleLowMemory();
12324 } else {
12325 app.thread.processInBackground();
12326 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012327 }
12328 } catch (Exception e) {
12329 // whatever.
12330 }
12331 }
12332
12333 /**
12334 * Returns true if things are idle enough to perform GCs.
12335 */
Josh Bartel7f208742010-02-25 11:01:44 -060012336 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012337 return mParallelBroadcasts.size() == 0
12338 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012339 && (mSleeping || (mMainStack.mResumedActivity != null &&
12340 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012341 }
12342
12343 /**
12344 * Perform GCs on all processes that are waiting for it, but only
12345 * if things are idle.
12346 */
12347 final void performAppGcsLocked() {
12348 final int N = mProcessesToGc.size();
12349 if (N <= 0) {
12350 return;
12351 }
Josh Bartel7f208742010-02-25 11:01:44 -060012352 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012353 while (mProcessesToGc.size() > 0) {
12354 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070012355 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012356 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
12357 <= SystemClock.uptimeMillis()) {
12358 // To avoid spamming the system, we will GC processes one
12359 // at a time, waiting a few seconds between each.
12360 performAppGcLocked(proc);
12361 scheduleAppGcsLocked();
12362 return;
12363 } else {
12364 // It hasn't been long enough since we last GCed this
12365 // process... put it in the list to wait for its time.
12366 addProcessToGcListLocked(proc);
12367 break;
12368 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012369 }
12370 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012371
12372 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012373 }
12374 }
12375
12376 /**
12377 * If all looks good, perform GCs on all processes waiting for them.
12378 */
12379 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060012380 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012381 performAppGcsLocked();
12382 return;
12383 }
12384 // Still not idle, wait some more.
12385 scheduleAppGcsLocked();
12386 }
12387
12388 /**
12389 * Schedule the execution of all pending app GCs.
12390 */
12391 final void scheduleAppGcsLocked() {
12392 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012393
12394 if (mProcessesToGc.size() > 0) {
12395 // Schedule a GC for the time to the next process.
12396 ProcessRecord proc = mProcessesToGc.get(0);
12397 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
12398
12399 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
12400 long now = SystemClock.uptimeMillis();
12401 if (when < (now+GC_TIMEOUT)) {
12402 when = now + GC_TIMEOUT;
12403 }
12404 mHandler.sendMessageAtTime(msg, when);
12405 }
12406 }
12407
12408 /**
12409 * Add a process to the array of processes waiting to be GCed. Keeps the
12410 * list in sorted order by the last GC time. The process can't already be
12411 * on the list.
12412 */
12413 final void addProcessToGcListLocked(ProcessRecord proc) {
12414 boolean added = false;
12415 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
12416 if (mProcessesToGc.get(i).lastRequestedGc <
12417 proc.lastRequestedGc) {
12418 added = true;
12419 mProcessesToGc.add(i+1, proc);
12420 break;
12421 }
12422 }
12423 if (!added) {
12424 mProcessesToGc.add(0, proc);
12425 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012426 }
12427
12428 /**
12429 * Set up to ask a process to GC itself. This will either do it
12430 * immediately, or put it on the list of processes to gc the next
12431 * time things are idle.
12432 */
12433 final void scheduleAppGcLocked(ProcessRecord app) {
12434 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012435 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012436 return;
12437 }
12438 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012439 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012440 scheduleAppGcsLocked();
12441 }
12442 }
12443
Dianne Hackborn287952c2010-09-22 22:34:31 -070012444 final void checkExcessivePowerUsageLocked(boolean doKills) {
12445 updateCpuStatsNow();
12446
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012447 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
Dianne Hackborn287952c2010-09-22 22:34:31 -070012448 boolean doWakeKills = doKills;
12449 boolean doCpuKills = doKills;
12450 if (mLastPowerCheckRealtime == 0) {
12451 doWakeKills = false;
12452 }
12453 if (mLastPowerCheckUptime == 0) {
12454 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012455 }
12456 if (stats.isScreenOn()) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070012457 doWakeKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012458 }
12459 final long curRealtime = SystemClock.elapsedRealtime();
Dianne Hackborn287952c2010-09-22 22:34:31 -070012460 final long realtimeSince = curRealtime - mLastPowerCheckRealtime;
12461 final long curUptime = SystemClock.uptimeMillis();
12462 final long uptimeSince = curUptime - mLastPowerCheckUptime;
12463 mLastPowerCheckRealtime = curRealtime;
12464 mLastPowerCheckUptime = curUptime;
12465 if (realtimeSince < WAKE_LOCK_MIN_CHECK_DURATION) {
12466 doWakeKills = false;
12467 }
12468 if (uptimeSince < CPU_MIN_CHECK_DURATION) {
12469 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012470 }
12471 int i = mLruProcesses.size();
12472 while (i > 0) {
12473 i--;
12474 ProcessRecord app = mLruProcesses.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012475 if (!app.keeping) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012476 long wtime;
12477 synchronized (stats) {
12478 wtime = stats.getProcessWakeTime(app.info.uid,
12479 app.pid, curRealtime);
12480 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012481 long wtimeUsed = wtime - app.lastWakeTime;
12482 long cputimeUsed = app.curCpuTime - app.lastCpuTime;
12483 if (DEBUG_POWER) {
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012484 StringBuilder sb = new StringBuilder(128);
12485 sb.append("Wake for ");
12486 app.toShortString(sb);
12487 sb.append(": over ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012488 TimeUtils.formatDuration(realtimeSince, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012489 sb.append(" used ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012490 TimeUtils.formatDuration(wtimeUsed, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012491 sb.append(" (");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012492 sb.append((wtimeUsed*100)/realtimeSince);
12493 sb.append("%)");
12494 Slog.i(TAG, sb.toString());
12495 sb.setLength(0);
12496 sb.append("CPU for ");
12497 app.toShortString(sb);
12498 sb.append(": over ");
12499 TimeUtils.formatDuration(uptimeSince, sb);
12500 sb.append(" used ");
12501 TimeUtils.formatDuration(cputimeUsed, sb);
12502 sb.append(" (");
12503 sb.append((cputimeUsed*100)/uptimeSince);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012504 sb.append("%)");
12505 Slog.i(TAG, sb.toString());
12506 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012507 // If a process has held a wake lock for more
12508 // than 50% of the time during this period,
12509 // that sounds pad. Kill!
Dianne Hackborn287952c2010-09-22 22:34:31 -070012510 if (doWakeKills && realtimeSince > 0
12511 && ((wtimeUsed*100)/realtimeSince) >= 50) {
12512 synchronized (stats) {
12513 stats.reportExcessiveWakeLocked(app.info.uid, app.processName,
12514 realtimeSince, wtimeUsed);
12515 }
12516 Slog.w(TAG, "Excessive wake lock in " + app.processName
12517 + " (pid " + app.pid + "): held " + wtimeUsed
12518 + " during " + realtimeSince);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012519 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12520 app.processName, app.setAdj, "excessive wake lock");
12521 Process.killProcessQuiet(app.pid);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012522 } else if (doCpuKills && uptimeSince > 0
12523 && ((cputimeUsed*100)/uptimeSince) >= 50) {
12524 synchronized (stats) {
12525 stats.reportExcessiveCpuLocked(app.info.uid, app.processName,
12526 uptimeSince, cputimeUsed);
12527 }
12528 Slog.w(TAG, "Excessive CPU in " + app.processName
12529 + " (pid " + app.pid + "): used " + cputimeUsed
12530 + " during " + uptimeSince);
12531 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12532 app.processName, app.setAdj, "excessive cpu");
12533 Process.killProcessQuiet(app.pid);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012534 } else {
12535 app.lastWakeTime = wtime;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012536 app.lastCpuTime = app.curCpuTime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012537 }
12538 }
12539 }
12540 }
12541
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012542 private final boolean updateOomAdjLocked(
12543 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
12544 app.hiddenAdj = hiddenAdj;
12545
12546 if (app.thread == null) {
12547 return true;
12548 }
12549
Dianne Hackborn287952c2010-09-22 22:34:31 -070012550 final boolean wasKeeping = app.keeping;
12551
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012552 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012553
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012554 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012555 if (app.curRawAdj != app.setRawAdj) {
12556 if (app.curRawAdj > FOREGROUND_APP_ADJ
12557 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
12558 // If this app is transitioning from foreground to
12559 // non-foreground, have it do a gc.
12560 scheduleAppGcLocked(app);
12561 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
12562 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
12563 // Likewise do a gc when an app is moving in to the
12564 // background (such as a service stopping).
12565 scheduleAppGcLocked(app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012566 }
12567
12568 if (wasKeeping && !app.keeping) {
12569 // This app is no longer something we want to keep. Note
12570 // its current wake lock time to later know to kill it if
12571 // it is not behaving well.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012572 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
12573 synchronized (stats) {
12574 app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
12575 app.pid, SystemClock.elapsedRealtime());
12576 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012577 app.lastCpuTime = app.curCpuTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012578 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012579
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012580 app.setRawAdj = app.curRawAdj;
12581 }
12582 if (adj != app.setAdj) {
12583 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012584 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012585 TAG, "Set app " + app.processName +
12586 " oom adj to " + adj);
12587 app.setAdj = adj;
12588 } else {
12589 return false;
12590 }
12591 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012592 if (app.setSchedGroup != app.curSchedGroup) {
12593 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012594 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012595 "Setting process group of " + app.processName
12596 + " to " + app.curSchedGroup);
12597 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070012598 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012599 try {
12600 Process.setProcessGroup(app.pid, app.curSchedGroup);
12601 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012602 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012603 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070012604 e.printStackTrace();
12605 } finally {
12606 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012607 }
12608 }
12609 if (false) {
12610 if (app.thread != null) {
12611 try {
12612 app.thread.setSchedulingGroup(app.curSchedGroup);
12613 } catch (RemoteException e) {
12614 }
12615 }
12616 }
12617 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012618 }
12619
12620 return true;
12621 }
12622
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012623 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012624 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012625 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012626 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012627 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012628 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012629 }
12630 }
12631 return resumedActivity;
12632 }
12633
12634 private final boolean updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012635 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012636 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
12637 int curAdj = app.curAdj;
12638 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
12639 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
12640
12641 mAdjSeq++;
12642
12643 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
12644 if (res) {
12645 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
12646 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
12647 if (nowHidden != wasHidden) {
12648 // Changed to/from hidden state, so apps after it in the LRU
12649 // list may also be changed.
12650 updateOomAdjLocked();
12651 }
12652 }
12653 return res;
12654 }
12655
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012656 final boolean updateOomAdjLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012657 boolean didOomAdj = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012658 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012659 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
12660
12661 if (false) {
12662 RuntimeException e = new RuntimeException();
12663 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080012664 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012665 }
12666
12667 mAdjSeq++;
12668
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012669 // Let's determine how many processes we have running vs.
12670 // how many slots we have for background processes; we may want
12671 // to put multiple processes in a slot of there are enough of
12672 // them.
12673 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
12674 int factor = (mLruProcesses.size()-4)/numSlots;
12675 if (factor < 1) factor = 1;
12676 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070012677 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012678
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012679 // First try updating the OOM adjustment for each of the
12680 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012681 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012682 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
12683 while (i > 0) {
12684 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012685 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012686 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012687 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012688 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012689 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012690 step++;
12691 if (step >= factor) {
12692 step = 0;
12693 curHiddenAdj++;
12694 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012695 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070012696 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070012697 if (!app.killedBackground) {
12698 numHidden++;
12699 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070012700 Slog.i(TAG, "No longer want " + app.processName
12701 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070012702 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12703 app.processName, app.setAdj, "too many background");
12704 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070012705 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070012706 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070012707 }
12708 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012709 } else {
12710 didOomAdj = false;
12711 }
12712 }
12713
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012714 // If we return false, we will fall back on killing processes to
12715 // have a fixed limit. Do this if a limit has been requested; else
12716 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012717 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
12718 }
12719
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012720 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012721 synchronized (this) {
12722 int i;
12723
12724 // First remove any unused application processes whose package
12725 // has been removed.
12726 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
12727 final ProcessRecord app = mRemovedProcesses.get(i);
12728 if (app.activities.size() == 0
12729 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012730 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012731 TAG, "Exiting empty application process "
12732 + app.processName + " ("
12733 + (app.thread != null ? app.thread.asBinder() : null)
12734 + ")\n");
12735 if (app.pid > 0 && app.pid != MY_PID) {
12736 Process.killProcess(app.pid);
12737 } else {
12738 try {
12739 app.thread.scheduleExit();
12740 } catch (Exception e) {
12741 // Ignore exceptions.
12742 }
12743 }
12744 cleanUpApplicationRecordLocked(app, false, -1);
12745 mRemovedProcesses.remove(i);
12746
12747 if (app.persistent) {
12748 if (app.persistent) {
12749 addAppLocked(app.info);
12750 }
12751 }
12752 }
12753 }
12754
12755 // Now try updating the OOM adjustment for each of the
12756 // application processes based on their current state.
12757 // If the setOomAdj() API is not supported, then go with our
12758 // back-up plan...
12759 if (!updateOomAdjLocked()) {
12760
12761 // Count how many processes are running services.
12762 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012763 for (i=mLruProcesses.size()-1; i>=0; i--) {
12764 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012765
12766 if (app.persistent || app.services.size() != 0
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012767 || app.curReceiver != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012768 // Don't count processes holding services against our
12769 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012770 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012771 TAG, "Not trimming app " + app + " with services: "
12772 + app.services);
12773 numServiceProcs++;
12774 }
12775 }
12776
12777 int curMaxProcs = mProcessLimit;
12778 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
12779 if (mAlwaysFinishActivities) {
12780 curMaxProcs = 1;
12781 }
12782 curMaxProcs += numServiceProcs;
12783
12784 // Quit as many processes as we can to get down to the desired
12785 // process count. First remove any processes that no longer
12786 // have activites running in them.
12787 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012788 i<mLruProcesses.size()
12789 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012790 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012791 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012792 // Quit an application only if it is not currently
12793 // running any activities.
12794 if (!app.persistent && app.activities.size() == 0
12795 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012796 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012797 TAG, "Exiting empty application process "
12798 + app.processName + " ("
12799 + (app.thread != null ? app.thread.asBinder() : null)
12800 + ")\n");
12801 if (app.pid > 0 && app.pid != MY_PID) {
12802 Process.killProcess(app.pid);
12803 } else {
12804 try {
12805 app.thread.scheduleExit();
12806 } catch (Exception e) {
12807 // Ignore exceptions.
12808 }
12809 }
12810 // todo: For now we assume the application is not buggy
12811 // or evil, and will quit as a result of our request.
12812 // Eventually we need to drive this off of the death
12813 // notification, and kill the process if it takes too long.
12814 cleanUpApplicationRecordLocked(app, false, i);
12815 i--;
12816 }
12817 }
12818
12819 // If we still have too many processes, now from the least
12820 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012821 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012822 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012823 " of " + curMaxProcs + " processes");
12824 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012825 i<mLruProcesses.size()
12826 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012827 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012828 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012829 // Quit the application only if we have a state saved for
12830 // all of its activities.
12831 boolean canQuit = !app.persistent && app.curReceiver == null
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012832 && app.services.size() == 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012833 int NUMA = app.activities.size();
12834 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012835 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012836 TAG, "Looking to quit " + app.processName);
12837 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012838 ActivityRecord r = app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012839 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012840 TAG, " " + r.intent.getComponent().flattenToShortString()
12841 + ": frozen=" + r.haveState + ", visible=" + r.visible);
12842 canQuit = (r.haveState || !r.stateNotNeeded)
12843 && !r.visible && r.stopped;
12844 }
12845 if (canQuit) {
12846 // Finish all of the activities, and then the app itself.
12847 for (j=0; j<NUMA; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012848 ActivityRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012849 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012850 r.stack.destroyActivityLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012851 }
12852 r.resultTo = null;
12853 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080012854 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012855 + app.processName + " ("
12856 + (app.thread != null ? app.thread.asBinder() : null)
12857 + ")\n");
12858 if (app.pid > 0 && app.pid != MY_PID) {
12859 Process.killProcess(app.pid);
12860 } else {
12861 try {
12862 app.thread.scheduleExit();
12863 } catch (Exception e) {
12864 // Ignore exceptions.
12865 }
12866 }
12867 // todo: For now we assume the application is not buggy
12868 // or evil, and will quit as a result of our request.
12869 // Eventually we need to drive this off of the death
12870 // notification, and kill the process if it takes too long.
12871 cleanUpApplicationRecordLocked(app, false, i);
12872 i--;
12873 //dump();
12874 }
12875 }
12876
12877 }
12878
12879 int curMaxActivities = MAX_ACTIVITIES;
12880 if (mAlwaysFinishActivities) {
12881 curMaxActivities = 1;
12882 }
12883
12884 // Finally, if there are too many activities now running, try to
12885 // finish as many as we can to get back down to the limit.
12886 for ( i=0;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012887 i<mMainStack.mLRUActivities.size()
12888 && mMainStack.mLRUActivities.size() > curMaxActivities;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012889 i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012890 final ActivityRecord r
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012891 = (ActivityRecord)mMainStack.mLRUActivities.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012892
12893 // We can finish this one if we have its icicle saved and
12894 // it is not persistent.
12895 if ((r.haveState || !r.stateNotNeeded) && !r.visible
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012896 && r.stopped && !r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012897 final int origSize = mMainStack.mLRUActivities.size();
12898 r.stack.destroyActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012899
12900 // This will remove it from the LRU list, so keep
12901 // our index at the same value. Note that this check to
12902 // see if the size changes is just paranoia -- if
12903 // something unexpected happens, we don't want to end up
12904 // in an infinite loop.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012905 if (origSize > mMainStack.mLRUActivities.size()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012906 i--;
12907 }
12908 }
12909 }
12910 }
12911 }
12912
12913 /** This method sends the specified signal to each of the persistent apps */
12914 public void signalPersistentProcesses(int sig) throws RemoteException {
12915 if (sig != Process.SIGNAL_USR1) {
12916 throw new SecurityException("Only SIGNAL_USR1 is allowed");
12917 }
12918
12919 synchronized (this) {
12920 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
12921 != PackageManager.PERMISSION_GRANTED) {
12922 throw new SecurityException("Requires permission "
12923 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
12924 }
12925
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012926 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
12927 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012928 if (r.thread != null && r.persistent) {
12929 Process.sendSignal(r.pid, sig);
12930 }
12931 }
12932 }
12933 }
12934
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012935 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012936 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012937
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012938 try {
12939 synchronized (this) {
12940 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
12941 // its own permission.
12942 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
12943 != PackageManager.PERMISSION_GRANTED) {
12944 throw new SecurityException("Requires permission "
12945 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012946 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012947
12948 if (start && fd == null) {
12949 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012950 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012951
12952 ProcessRecord proc = null;
12953 try {
12954 int pid = Integer.parseInt(process);
12955 synchronized (mPidsSelfLocked) {
12956 proc = mPidsSelfLocked.get(pid);
12957 }
12958 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012959 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012960
12961 if (proc == null) {
12962 HashMap<String, SparseArray<ProcessRecord>> all
12963 = mProcessNames.getMap();
12964 SparseArray<ProcessRecord> procs = all.get(process);
12965 if (procs != null && procs.size() > 0) {
12966 proc = procs.valueAt(0);
12967 }
12968 }
12969
12970 if (proc == null || proc.thread == null) {
12971 throw new IllegalArgumentException("Unknown process: " + process);
12972 }
12973
Dianne Hackbornf02e57b2011-03-01 22:21:04 -080012974 boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
12975 if (!isDebuggable) {
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012976 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
12977 throw new SecurityException("Process not debuggable: " + proc);
12978 }
12979 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012980
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012981 proc.thread.profilerControl(start, path, fd);
12982 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012983 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012984 }
12985 } catch (RemoteException e) {
12986 throw new IllegalStateException("Process disappeared");
12987 } finally {
12988 if (fd != null) {
12989 try {
12990 fd.close();
12991 } catch (IOException e) {
12992 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012993 }
12994 }
12995 }
Andy McFadden824c5102010-07-09 16:26:57 -070012996
12997 public boolean dumpHeap(String process, boolean managed,
12998 String path, ParcelFileDescriptor fd) throws RemoteException {
12999
13000 try {
13001 synchronized (this) {
13002 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
13003 // its own permission (same as profileControl).
13004 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
13005 != PackageManager.PERMISSION_GRANTED) {
13006 throw new SecurityException("Requires permission "
13007 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
13008 }
13009
13010 if (fd == null) {
13011 throw new IllegalArgumentException("null fd");
13012 }
13013
13014 ProcessRecord proc = null;
13015 try {
13016 int pid = Integer.parseInt(process);
13017 synchronized (mPidsSelfLocked) {
13018 proc = mPidsSelfLocked.get(pid);
13019 }
13020 } catch (NumberFormatException e) {
13021 }
13022
13023 if (proc == null) {
13024 HashMap<String, SparseArray<ProcessRecord>> all
13025 = mProcessNames.getMap();
13026 SparseArray<ProcessRecord> procs = all.get(process);
13027 if (procs != null && procs.size() > 0) {
13028 proc = procs.valueAt(0);
13029 }
13030 }
13031
13032 if (proc == null || proc.thread == null) {
13033 throw new IllegalArgumentException("Unknown process: " + process);
13034 }
13035
Dianne Hackbornf02e57b2011-03-01 22:21:04 -080013036 boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
13037 if (!isDebuggable) {
Andy McFadden824c5102010-07-09 16:26:57 -070013038 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
13039 throw new SecurityException("Process not debuggable: " + proc);
13040 }
13041 }
13042
13043 proc.thread.dumpHeap(managed, path, fd);
13044 fd = null;
13045 return true;
13046 }
13047 } catch (RemoteException e) {
13048 throw new IllegalStateException("Process disappeared");
13049 } finally {
13050 if (fd != null) {
13051 try {
13052 fd.close();
13053 } catch (IOException e) {
13054 }
13055 }
13056 }
13057 }
13058
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013059 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
13060 public void monitor() {
13061 synchronized (this) { }
13062 }
Svetoslav Ganov54d068e2011-03-02 12:58:40 -080013063
13064 public void onCoreSettingsChange(Bundle settings) {
13065 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
13066 ProcessRecord processRecord = mLruProcesses.get(i);
13067 try {
13068 if (processRecord.thread != null) {
13069 processRecord.thread.setCoreSettings(settings);
13070 }
13071 } catch (RemoteException re) {
13072 /* ignore */
13073 }
13074 }
13075 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013076}