blob: 54cc885bdac994c7ff9d1c72ef543c744ba3e97d [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];
Dianne Hackborn52b0ce02011-04-14 13:09:32 -07003917 if (intent != null) {
3918 if (intent.hasFileDescriptors()) {
3919 throw new IllegalArgumentException("File descriptors passed in Intent");
3920 }
3921 if (type == INTENT_SENDER_BROADCAST &&
3922 (intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
3923 throw new IllegalArgumentException(
3924 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
3925 }
3926 intents[i] = new Intent(intent);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003927 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003928 }
3929 if (resolvedTypes != null && resolvedTypes.length != intents.length) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003930 throw new IllegalArgumentException(
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003931 "Intent array length does not match resolvedTypes length");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003932 }
3933 }
3934
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003935 synchronized(this) {
3936 int callingUid = Binder.getCallingUid();
3937 try {
3938 if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
3939 Process.supportsProcesses()) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003940 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003941 .getPackageUid(packageName);
3942 if (uid != Binder.getCallingUid()) {
3943 String msg = "Permission Denial: getIntentSender() from pid="
3944 + Binder.getCallingPid()
3945 + ", uid=" + Binder.getCallingUid()
3946 + ", (need uid=" + uid + ")"
3947 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003948 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003949 throw new SecurityException(msg);
3950 }
3951 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003952
3953 return getIntentSenderLocked(type, packageName, callingUid,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003954 token, resultWho, requestCode, intents, resolvedTypes, flags);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003955
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003956 } catch (RemoteException e) {
3957 throw new SecurityException(e);
3958 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003959 }
3960 }
3961
3962 IIntentSender getIntentSenderLocked(int type,
3963 String packageName, int callingUid, IBinder token, String resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003964 int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003965 ActivityRecord activity = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07003966 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003967 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003968 if (index < 0) {
3969 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003970 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003971 activity = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003972 if (activity.finishing) {
3973 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003974 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07003975 }
3976
3977 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
3978 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
3979 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
3980 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
3981 |PendingIntent.FLAG_UPDATE_CURRENT);
3982
3983 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
3984 type, packageName, activity, resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003985 requestCode, intents, resolvedTypes, flags);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003986 WeakReference<PendingIntentRecord> ref;
3987 ref = mIntentSenderRecords.get(key);
3988 PendingIntentRecord rec = ref != null ? ref.get() : null;
3989 if (rec != null) {
3990 if (!cancelCurrent) {
3991 if (updateCurrent) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003992 if (rec.key.requestIntent != null) {
3993 rec.key.requestIntent.replaceExtras(intents != null ? intents[0] : null);
3994 }
3995 if (intents != null) {
3996 intents[intents.length-1] = rec.key.requestIntent;
3997 rec.key.allIntents = intents;
3998 rec.key.allResolvedTypes = resolvedTypes;
3999 } else {
4000 rec.key.allIntents = null;
4001 rec.key.allResolvedTypes = null;
4002 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004003 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004004 return rec;
4005 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004006 rec.canceled = true;
4007 mIntentSenderRecords.remove(key);
4008 }
4009 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004010 return rec;
4011 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004012 rec = new PendingIntentRecord(this, key, callingUid);
4013 mIntentSenderRecords.put(key, rec.ref);
4014 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
4015 if (activity.pendingResults == null) {
4016 activity.pendingResults
4017 = new HashSet<WeakReference<PendingIntentRecord>>();
4018 }
4019 activity.pendingResults.add(rec.ref);
4020 }
4021 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004022 }
4023
4024 public void cancelIntentSender(IIntentSender sender) {
4025 if (!(sender instanceof PendingIntentRecord)) {
4026 return;
4027 }
4028 synchronized(this) {
4029 PendingIntentRecord rec = (PendingIntentRecord)sender;
4030 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004031 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004032 .getPackageUid(rec.key.packageName);
4033 if (uid != Binder.getCallingUid()) {
4034 String msg = "Permission Denial: cancelIntentSender() from pid="
4035 + Binder.getCallingPid()
4036 + ", uid=" + Binder.getCallingUid()
4037 + " is not allowed to cancel packges "
4038 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004039 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004040 throw new SecurityException(msg);
4041 }
4042 } catch (RemoteException e) {
4043 throw new SecurityException(e);
4044 }
4045 cancelIntentSenderLocked(rec, true);
4046 }
4047 }
4048
4049 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
4050 rec.canceled = true;
4051 mIntentSenderRecords.remove(rec.key);
4052 if (cleanActivity && rec.key.activity != null) {
4053 rec.key.activity.pendingResults.remove(rec.ref);
4054 }
4055 }
4056
4057 public String getPackageForIntentSender(IIntentSender pendingResult) {
4058 if (!(pendingResult instanceof PendingIntentRecord)) {
4059 return null;
4060 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07004061 try {
4062 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
4063 return res.key.packageName;
4064 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004065 }
4066 return null;
4067 }
4068
4069 public void setProcessLimit(int max) {
4070 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4071 "setProcessLimit()");
4072 mProcessLimit = max;
4073 }
4074
4075 public int getProcessLimit() {
4076 return mProcessLimit;
4077 }
4078
4079 void foregroundTokenDied(ForegroundToken token) {
4080 synchronized (ActivityManagerService.this) {
4081 synchronized (mPidsSelfLocked) {
4082 ForegroundToken cur
4083 = mForegroundProcesses.get(token.pid);
4084 if (cur != token) {
4085 return;
4086 }
4087 mForegroundProcesses.remove(token.pid);
4088 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
4089 if (pr == null) {
4090 return;
4091 }
4092 pr.forcingToForeground = null;
4093 pr.foregroundServices = false;
4094 }
4095 updateOomAdjLocked();
4096 }
4097 }
4098
4099 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
4100 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4101 "setProcessForeground()");
4102 synchronized(this) {
4103 boolean changed = false;
4104
4105 synchronized (mPidsSelfLocked) {
4106 ProcessRecord pr = mPidsSelfLocked.get(pid);
4107 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004108 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004109 return;
4110 }
4111 ForegroundToken oldToken = mForegroundProcesses.get(pid);
4112 if (oldToken != null) {
4113 oldToken.token.unlinkToDeath(oldToken, 0);
4114 mForegroundProcesses.remove(pid);
4115 pr.forcingToForeground = null;
4116 changed = true;
4117 }
4118 if (isForeground && token != null) {
4119 ForegroundToken newToken = new ForegroundToken() {
4120 public void binderDied() {
4121 foregroundTokenDied(this);
4122 }
4123 };
4124 newToken.pid = pid;
4125 newToken.token = token;
4126 try {
4127 token.linkToDeath(newToken, 0);
4128 mForegroundProcesses.put(pid, newToken);
4129 pr.forcingToForeground = token;
4130 changed = true;
4131 } catch (RemoteException e) {
4132 // If the process died while doing this, we will later
4133 // do the cleanup with the process death link.
4134 }
4135 }
4136 }
4137
4138 if (changed) {
4139 updateOomAdjLocked();
4140 }
4141 }
4142 }
4143
4144 // =========================================================
4145 // PERMISSIONS
4146 // =========================================================
4147
4148 static class PermissionController extends IPermissionController.Stub {
4149 ActivityManagerService mActivityManagerService;
4150 PermissionController(ActivityManagerService activityManagerService) {
4151 mActivityManagerService = activityManagerService;
4152 }
4153
4154 public boolean checkPermission(String permission, int pid, int uid) {
4155 return mActivityManagerService.checkPermission(permission, pid,
4156 uid) == PackageManager.PERMISSION_GRANTED;
4157 }
4158 }
4159
4160 /**
4161 * This can be called with or without the global lock held.
4162 */
4163 int checkComponentPermission(String permission, int pid, int uid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004164 int owningUid, boolean exported) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004165 // We might be performing an operation on behalf of an indirect binder
4166 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
4167 // client identity accordingly before proceeding.
4168 Identity tlsIdentity = sCallerIdentity.get();
4169 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004170 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004171 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
4172 uid = tlsIdentity.uid;
4173 pid = tlsIdentity.pid;
4174 }
4175
4176 // Root, system server and our own process get to do everything.
4177 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID ||
4178 !Process.supportsProcesses()) {
4179 return PackageManager.PERMISSION_GRANTED;
4180 }
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004181 // If there is a uid that owns whatever is being accessed, it has
4182 // blanket access to it regardless of the permissions it requires.
4183 if (owningUid >= 0 && uid == owningUid) {
4184 return PackageManager.PERMISSION_GRANTED;
4185 }
4186 // If the target is not exported, then nobody else can get to it.
4187 if (!exported) {
4188 Slog.w(TAG, "Permission denied: checkComponentPermission() owningUid=" + owningUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004189 return PackageManager.PERMISSION_DENIED;
4190 }
4191 if (permission == null) {
4192 return PackageManager.PERMISSION_GRANTED;
4193 }
4194 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004195 return AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004196 .checkUidPermission(permission, uid);
4197 } catch (RemoteException e) {
4198 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004199 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004200 }
4201 return PackageManager.PERMISSION_DENIED;
4202 }
4203
4204 /**
4205 * As the only public entry point for permissions checking, this method
4206 * can enforce the semantic that requesting a check on a null global
4207 * permission is automatically denied. (Internally a null permission
4208 * string is used when calling {@link #checkComponentPermission} in cases
4209 * when only uid-based security is needed.)
4210 *
4211 * This can be called with or without the global lock held.
4212 */
4213 public int checkPermission(String permission, int pid, int uid) {
4214 if (permission == null) {
4215 return PackageManager.PERMISSION_DENIED;
4216 }
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004217 return checkComponentPermission(permission, pid, uid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004218 }
4219
4220 /**
4221 * Binder IPC calls go through the public entry point.
4222 * This can be called with or without the global lock held.
4223 */
4224 int checkCallingPermission(String permission) {
4225 return checkPermission(permission,
4226 Binder.getCallingPid(),
4227 Binder.getCallingUid());
4228 }
4229
4230 /**
4231 * This can be called with or without the global lock held.
4232 */
4233 void enforceCallingPermission(String permission, String func) {
4234 if (checkCallingPermission(permission)
4235 == PackageManager.PERMISSION_GRANTED) {
4236 return;
4237 }
4238
4239 String msg = "Permission Denial: " + func + " from pid="
4240 + Binder.getCallingPid()
4241 + ", uid=" + Binder.getCallingUid()
4242 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004243 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004244 throw new SecurityException(msg);
4245 }
4246
4247 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
Dianne Hackborn48058e82010-09-27 16:53:23 -07004248 ProviderInfo pi, Uri uri, int uid, int modeFlags) {
4249 boolean readPerm = (modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0;
4250 boolean writePerm = (modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0;
4251 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4252 "checkHoldingPermissionsLocked: uri=" + uri + " uid=" + uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004253 try {
Dianne Hackborn48058e82010-09-27 16:53:23 -07004254 // Is the component private from the target uid?
4255 final boolean prv = !pi.exported && pi.applicationInfo.uid != uid;
4256
4257 // Acceptable if the there is no read permission needed from the
4258 // target or the target is holding the read permission.
4259 if (!readPerm) {
4260 if ((!prv && pi.readPermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004261 (pm.checkUidPermission(pi.readPermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004262 == PackageManager.PERMISSION_GRANTED)) {
4263 readPerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004264 }
4265 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004266
4267 // Acceptable if the there is no write permission needed from the
4268 // target or the target is holding the read permission.
4269 if (!writePerm) {
4270 if (!prv && (pi.writePermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004271 (pm.checkUidPermission(pi.writePermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004272 == PackageManager.PERMISSION_GRANTED)) {
4273 writePerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004274 }
4275 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004276
4277 // Acceptable if there is a path permission matching the URI that
4278 // the target holds the permission on.
4279 PathPermission[] pps = pi.pathPermissions;
4280 if (pps != null && (!readPerm || !writePerm)) {
4281 final String path = uri.getPath();
4282 int i = pps.length;
4283 while (i > 0 && (!readPerm || !writePerm)) {
4284 i--;
4285 PathPermission pp = pps[i];
4286 if (!readPerm) {
4287 final String pprperm = pp.getReadPermission();
4288 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking read perm for "
4289 + pprperm + " for " + pp.getPath()
4290 + ": match=" + pp.match(path)
4291 + " check=" + pm.checkUidPermission(pprperm, uid));
4292 if (pprperm != null && pp.match(path) &&
4293 (pm.checkUidPermission(pprperm, uid)
4294 == PackageManager.PERMISSION_GRANTED)) {
4295 readPerm = true;
4296 }
4297 }
4298 if (!writePerm) {
4299 final String ppwperm = pp.getWritePermission();
4300 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking write perm "
4301 + ppwperm + " for " + pp.getPath()
4302 + ": match=" + pp.match(path)
4303 + " check=" + pm.checkUidPermission(ppwperm, uid));
4304 if (ppwperm != null && pp.match(path) &&
4305 (pm.checkUidPermission(ppwperm, uid)
4306 == PackageManager.PERMISSION_GRANTED)) {
4307 writePerm = true;
4308 }
4309 }
4310 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004311 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004312 } catch (RemoteException e) {
4313 return false;
4314 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004315
4316 return readPerm && writePerm;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004317 }
4318
4319 private final boolean checkUriPermissionLocked(Uri uri, int uid,
4320 int modeFlags) {
4321 // Root gets to do everything.
4322 if (uid == 0 || !Process.supportsProcesses()) {
4323 return true;
4324 }
4325 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
4326 if (perms == null) return false;
4327 UriPermission perm = perms.get(uri);
4328 if (perm == null) return false;
4329 return (modeFlags&perm.modeFlags) == modeFlags;
4330 }
4331
4332 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
4333 // Another redirected-binder-call permissions check as in
4334 // {@link checkComponentPermission}.
4335 Identity tlsIdentity = sCallerIdentity.get();
4336 if (tlsIdentity != null) {
4337 uid = tlsIdentity.uid;
4338 pid = tlsIdentity.pid;
4339 }
4340
4341 // Our own process gets to do everything.
4342 if (pid == MY_PID) {
4343 return PackageManager.PERMISSION_GRANTED;
4344 }
4345 synchronized(this) {
4346 return checkUriPermissionLocked(uri, uid, modeFlags)
4347 ? PackageManager.PERMISSION_GRANTED
4348 : PackageManager.PERMISSION_DENIED;
4349 }
4350 }
4351
Dianne Hackborn39792d22010-08-19 18:01:52 -07004352 /**
4353 * Check if the targetPkg can be granted permission to access uri by
4354 * the callingUid using the given modeFlags. Throws a security exception
4355 * if callingUid is not allowed to do this. Returns the uid of the target
4356 * if the URI permission grant should be performed; returns -1 if it is not
4357 * needed (for example targetPkg already has permission to access the URI).
4358 */
4359 int checkGrantUriPermissionLocked(int callingUid, String targetPkg,
4360 Uri uri, int modeFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004361 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4362 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4363 if (modeFlags == 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004364 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004365 }
4366
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004367 if (targetPkg != null) {
4368 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4369 "Checking grant " + targetPkg + " permission to " + uri);
4370 }
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004371
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004372 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004373
4374 // If this is not a content: uri, we can't do anything with it.
4375 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004376 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004377 "Can't grant URI permission for non-content URI: " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004378 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004379 }
4380
4381 String name = uri.getAuthority();
4382 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004383 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004384 if (cpr != null) {
4385 pi = cpr.info;
4386 } else {
4387 try {
4388 pi = pm.resolveContentProvider(name,
4389 PackageManager.GET_URI_PERMISSION_PATTERNS);
4390 } catch (RemoteException ex) {
4391 }
4392 }
4393 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004394 Slog.w(TAG, "No content provider found for: " + name);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004395 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004396 }
4397
4398 int targetUid;
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004399 if (targetPkg != null) {
4400 try {
4401 targetUid = pm.getPackageUid(targetPkg);
4402 if (targetUid < 0) {
4403 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4404 "Can't grant URI permission no uid for: " + targetPkg);
4405 return -1;
4406 }
4407 } catch (RemoteException ex) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004408 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004409 }
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004410 } else {
4411 targetUid = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004412 }
4413
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004414 if (targetUid >= 0) {
4415 // First... does the target actually need this permission?
4416 if (checkHoldingPermissionsLocked(pm, pi, uri, targetUid, modeFlags)) {
4417 // No need to grant the target this permission.
4418 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4419 "Target " + targetPkg + " already has full permission to " + uri);
4420 return -1;
4421 }
4422 } else {
4423 // First... there is no target package, so can anyone access it?
4424 boolean allowed = pi.exported;
4425 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4426 if (pi.readPermission != null) {
4427 allowed = false;
4428 }
4429 }
4430 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4431 if (pi.writePermission != null) {
4432 allowed = false;
4433 }
4434 }
4435 if (allowed) {
4436 return -1;
4437 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004438 }
4439
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004440 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004441 if (!pi.grantUriPermissions) {
4442 throw new SecurityException("Provider " + pi.packageName
4443 + "/" + pi.name
4444 + " does not allow granting of Uri permissions (uri "
4445 + uri + ")");
4446 }
4447 if (pi.uriPermissionPatterns != null) {
4448 final int N = pi.uriPermissionPatterns.length;
4449 boolean allowed = false;
4450 for (int i=0; i<N; i++) {
4451 if (pi.uriPermissionPatterns[i] != null
4452 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
4453 allowed = true;
4454 break;
4455 }
4456 }
4457 if (!allowed) {
4458 throw new SecurityException("Provider " + pi.packageName
4459 + "/" + pi.name
4460 + " does not allow granting of permission to path of Uri "
4461 + uri);
4462 }
4463 }
4464
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004465 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004466 // this uri?
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004467 if (callingUid != Process.myUid()) {
4468 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
4469 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4470 throw new SecurityException("Uid " + callingUid
4471 + " does not have permission to uri " + uri);
4472 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004473 }
4474 }
4475
Dianne Hackborn39792d22010-08-19 18:01:52 -07004476 return targetUid;
4477 }
4478
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004479 public int checkGrantUriPermission(int callingUid, String targetPkg,
4480 Uri uri, int modeFlags) {
4481 synchronized(this) {
4482 return checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4483 }
4484 }
4485
Dianne Hackborn39792d22010-08-19 18:01:52 -07004486 void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg,
4487 Uri uri, int modeFlags, UriPermissionOwner owner) {
4488 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4489 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4490 if (modeFlags == 0) {
4491 return;
4492 }
4493
4494 // So here we are: the caller has the assumed permission
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004495 // to the uri, and the target doesn't. Let's now give this to
4496 // the target.
4497
Joe Onorato8a9b2202010-02-26 18:56:32 -08004498 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004499 "Granting " + targetPkg + "/" + targetUid + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004500
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004501 HashMap<Uri, UriPermission> targetUris
4502 = mGrantedUriPermissions.get(targetUid);
4503 if (targetUris == null) {
4504 targetUris = new HashMap<Uri, UriPermission>();
4505 mGrantedUriPermissions.put(targetUid, targetUris);
4506 }
4507
4508 UriPermission perm = targetUris.get(uri);
4509 if (perm == null) {
4510 perm = new UriPermission(targetUid, uri);
4511 targetUris.put(uri, perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004512 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004513
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004514 perm.modeFlags |= modeFlags;
Dianne Hackborn39792d22010-08-19 18:01:52 -07004515 if (owner == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004516 perm.globalModeFlags |= modeFlags;
Vairavan Srinivasan91c12c22011-01-21 18:26:06 -08004517 } else {
4518 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4519 perm.readOwners.add(owner);
4520 owner.addReadPermission(perm);
4521 }
4522 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4523 perm.writeOwners.add(owner);
4524 owner.addWritePermission(perm);
4525 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004526 }
4527 }
4528
Dianne Hackborn39792d22010-08-19 18:01:52 -07004529 void grantUriPermissionLocked(int callingUid,
4530 String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) {
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004531 if (targetPkg == null) {
4532 throw new NullPointerException("targetPkg");
4533 }
4534
Dianne Hackborn39792d22010-08-19 18:01:52 -07004535 int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4536 if (targetUid < 0) {
4537 return;
4538 }
4539
4540 grantUriPermissionUncheckedLocked(targetUid, targetPkg, uri, modeFlags, owner);
4541 }
4542
4543 /**
4544 * Like checkGrantUriPermissionLocked, but takes an Intent.
4545 */
4546 int checkGrantUriPermissionFromIntentLocked(int callingUid,
4547 String targetPkg, Intent intent) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07004548 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004549 "Checking URI perm to " + (intent != null ? intent.getData() : null)
Dianne Hackbornb424b632010-08-18 15:59:05 -07004550 + " from " + intent + "; flags=0x"
4551 + Integer.toHexString(intent != null ? intent.getFlags() : 0));
4552
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004553 if (targetPkg == null) {
4554 throw new NullPointerException("targetPkg");
4555 }
4556
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004557 if (intent == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004558 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004559 }
4560 Uri data = intent.getData();
4561 if (data == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004562 return -1;
4563 }
4564 return checkGrantUriPermissionLocked(callingUid, targetPkg, data,
4565 intent.getFlags());
4566 }
4567
4568 /**
4569 * Like grantUriPermissionUncheckedLocked, but takes an Intent.
4570 */
4571 void grantUriPermissionUncheckedFromIntentLocked(int targetUid,
4572 String targetPkg, Intent intent, UriPermissionOwner owner) {
4573 grantUriPermissionUncheckedLocked(targetUid, targetPkg, intent.getData(),
4574 intent.getFlags(), owner);
4575 }
4576
4577 void grantUriPermissionFromIntentLocked(int callingUid,
4578 String targetPkg, Intent intent, UriPermissionOwner owner) {
4579 int targetUid = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg, intent);
4580 if (targetUid < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004581 return;
4582 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07004583
4584 grantUriPermissionUncheckedFromIntentLocked(targetUid, targetPkg, intent, owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004585 }
4586
4587 public void grantUriPermission(IApplicationThread caller, String targetPkg,
4588 Uri uri, int modeFlags) {
4589 synchronized(this) {
4590 final ProcessRecord r = getRecordForAppLocked(caller);
4591 if (r == null) {
4592 throw new SecurityException("Unable to find app for caller "
4593 + caller
4594 + " when granting permission to uri " + uri);
4595 }
4596 if (targetPkg == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004597 throw new IllegalArgumentException("null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004598 }
4599 if (uri == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004600 throw new IllegalArgumentException("null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004601 }
4602
4603 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
4604 null);
4605 }
4606 }
4607
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004608 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004609 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
4610 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
4611 HashMap<Uri, UriPermission> perms
4612 = mGrantedUriPermissions.get(perm.uid);
4613 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004614 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004615 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004616 perms.remove(perm.uri);
4617 if (perms.size() == 0) {
4618 mGrantedUriPermissions.remove(perm.uid);
4619 }
4620 }
4621 }
4622 }
4623
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004624 private void revokeUriPermissionLocked(int callingUid, Uri uri,
4625 int modeFlags) {
4626 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4627 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4628 if (modeFlags == 0) {
4629 return;
4630 }
4631
Joe Onorato8a9b2202010-02-26 18:56:32 -08004632 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004633 "Revoking all granted permissions to " + uri);
4634
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004635 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004636
4637 final String authority = uri.getAuthority();
4638 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004639 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004640 if (cpr != null) {
4641 pi = cpr.info;
4642 } else {
4643 try {
4644 pi = pm.resolveContentProvider(authority,
4645 PackageManager.GET_URI_PERMISSION_PATTERNS);
4646 } catch (RemoteException ex) {
4647 }
4648 }
4649 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004650 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004651 return;
4652 }
4653
4654 // Does the caller have this permission on the URI?
Dianne Hackborn48058e82010-09-27 16:53:23 -07004655 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004656 // Right now, if you are not the original owner of the permission,
4657 // you are not allowed to revoke it.
4658 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4659 throw new SecurityException("Uid " + callingUid
4660 + " does not have permission to uri " + uri);
4661 //}
4662 }
4663
4664 // Go through all of the permissions and remove any that match.
4665 final List<String> SEGMENTS = uri.getPathSegments();
4666 if (SEGMENTS != null) {
4667 final int NS = SEGMENTS.size();
4668 int N = mGrantedUriPermissions.size();
4669 for (int i=0; i<N; i++) {
4670 HashMap<Uri, UriPermission> perms
4671 = mGrantedUriPermissions.valueAt(i);
4672 Iterator<UriPermission> it = perms.values().iterator();
4673 toploop:
4674 while (it.hasNext()) {
4675 UriPermission perm = it.next();
4676 Uri targetUri = perm.uri;
4677 if (!authority.equals(targetUri.getAuthority())) {
4678 continue;
4679 }
4680 List<String> targetSegments = targetUri.getPathSegments();
4681 if (targetSegments == null) {
4682 continue;
4683 }
4684 if (targetSegments.size() < NS) {
4685 continue;
4686 }
4687 for (int j=0; j<NS; j++) {
4688 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
4689 continue toploop;
4690 }
4691 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004692 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004693 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004694 perm.clearModes(modeFlags);
4695 if (perm.modeFlags == 0) {
4696 it.remove();
4697 }
4698 }
4699 if (perms.size() == 0) {
4700 mGrantedUriPermissions.remove(
4701 mGrantedUriPermissions.keyAt(i));
4702 N--;
4703 i--;
4704 }
4705 }
4706 }
4707 }
4708
4709 public void revokeUriPermission(IApplicationThread caller, Uri uri,
4710 int modeFlags) {
4711 synchronized(this) {
4712 final ProcessRecord r = getRecordForAppLocked(caller);
4713 if (r == null) {
4714 throw new SecurityException("Unable to find app for caller "
4715 + caller
4716 + " when revoking permission to uri " + uri);
4717 }
4718 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004719 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004720 return;
4721 }
4722
4723 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4724 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4725 if (modeFlags == 0) {
4726 return;
4727 }
4728
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004729 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004730
4731 final String authority = uri.getAuthority();
4732 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004733 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004734 if (cpr != null) {
4735 pi = cpr.info;
4736 } else {
4737 try {
4738 pi = pm.resolveContentProvider(authority,
4739 PackageManager.GET_URI_PERMISSION_PATTERNS);
4740 } catch (RemoteException ex) {
4741 }
4742 }
4743 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004744 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004745 return;
4746 }
4747
4748 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
4749 }
4750 }
4751
Dianne Hackborn7e269642010-08-25 19:50:20 -07004752 @Override
4753 public IBinder newUriPermissionOwner(String name) {
4754 synchronized(this) {
4755 UriPermissionOwner owner = new UriPermissionOwner(this, name);
4756 return owner.getExternalTokenLocked();
4757 }
4758 }
4759
4760 @Override
4761 public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg,
4762 Uri uri, int modeFlags) {
4763 synchronized(this) {
4764 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4765 if (owner == null) {
4766 throw new IllegalArgumentException("Unknown owner: " + token);
4767 }
4768 if (fromUid != Binder.getCallingUid()) {
4769 if (Binder.getCallingUid() != Process.myUid()) {
4770 // Only system code can grant URI permissions on behalf
4771 // of other users.
4772 throw new SecurityException("nice try");
4773 }
4774 }
4775 if (targetPkg == null) {
4776 throw new IllegalArgumentException("null target");
4777 }
4778 if (uri == null) {
4779 throw new IllegalArgumentException("null uri");
4780 }
4781
4782 grantUriPermissionLocked(fromUid, targetPkg, uri, modeFlags, owner);
4783 }
4784 }
4785
4786 @Override
4787 public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode) {
4788 synchronized(this) {
4789 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4790 if (owner == null) {
4791 throw new IllegalArgumentException("Unknown owner: " + token);
4792 }
4793
4794 if (uri == null) {
4795 owner.removeUriPermissionsLocked(mode);
4796 } else {
4797 owner.removeUriPermissionLocked(uri, mode);
4798 }
4799 }
4800 }
4801
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004802 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
4803 synchronized (this) {
4804 ProcessRecord app =
4805 who != null ? getRecordForAppLocked(who) : null;
4806 if (app == null) return;
4807
4808 Message msg = Message.obtain();
4809 msg.what = WAIT_FOR_DEBUGGER_MSG;
4810 msg.obj = app;
4811 msg.arg1 = waiting ? 1 : 0;
4812 mHandler.sendMessage(msg);
4813 }
4814 }
4815
4816 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
4817 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08004818 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004819 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08004820 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004821 }
4822
4823 // =========================================================
4824 // TASK MANAGEMENT
4825 // =========================================================
4826
4827 public List getTasks(int maxNum, int flags,
4828 IThumbnailReceiver receiver) {
4829 ArrayList list = new ArrayList();
4830
4831 PendingThumbnailsRecord pending = null;
4832 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004833 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004834
4835 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004836 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004837 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
4838 + ", receiver=" + receiver);
4839
4840 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
4841 != PackageManager.PERMISSION_GRANTED) {
4842 if (receiver != null) {
4843 // If the caller wants to wait for pending thumbnails,
4844 // it ain't gonna get them.
4845 try {
4846 receiver.finished();
4847 } catch (RemoteException ex) {
4848 }
4849 }
4850 String msg = "Permission Denial: getTasks() from pid="
4851 + Binder.getCallingPid()
4852 + ", uid=" + Binder.getCallingUid()
4853 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004854 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004855 throw new SecurityException(msg);
4856 }
4857
Dianne Hackbornd2835932010-12-13 16:28:46 -08004858 final boolean canReadFb = (flags&ActivityManager.TASKS_GET_THUMBNAILS) != 0
4859 && checkCallingPermission(
4860 android.Manifest.permission.READ_FRAME_BUFFER)
4861 == PackageManager.PERMISSION_GRANTED;
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08004862
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004863 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004864 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004865 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004866 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004867 CharSequence topDescription = null;
4868 TaskRecord curTask = null;
4869 int numActivities = 0;
4870 int numRunning = 0;
4871 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004872 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004873 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004874 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004875
4876 // Initialize state for next task if needed.
4877 if (top == null ||
4878 (top.state == ActivityState.INITIALIZING
4879 && top.task == r.task)) {
4880 top = r;
4881 topDescription = r.description;
4882 curTask = r.task;
4883 numActivities = numRunning = 0;
4884 }
4885
4886 // Add 'r' into the current task.
4887 numActivities++;
4888 if (r.app != null && r.app.thread != null) {
4889 numRunning++;
4890 }
4891 if (topDescription == null) {
4892 topDescription = r.description;
4893 }
4894
Joe Onorato8a9b2202010-02-26 18:56:32 -08004895 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004896 TAG, r.intent.getComponent().flattenToShortString()
4897 + ": task=" + r.task);
4898
4899 // If the next one is a different task, generate a new
4900 // TaskInfo entry for what we have.
4901 if (next == null || next.task != curTask) {
4902 ActivityManager.RunningTaskInfo ci
4903 = new ActivityManager.RunningTaskInfo();
4904 ci.id = curTask.taskId;
4905 ci.baseActivity = r.intent.getComponent();
4906 ci.topActivity = top.intent.getComponent();
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08004907 if (canReadFb) {
4908 if (top.thumbnail != null) {
4909 ci.thumbnail = top.thumbnail;
4910 } else if (top.state == ActivityState.RESUMED) {
Dianne Hackbornd2835932010-12-13 16:28:46 -08004911 ci.thumbnail = top.stack.screenshotActivities(top);
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08004912 }
4913 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004914 ci.description = topDescription;
4915 ci.numActivities = numActivities;
4916 ci.numRunning = numRunning;
4917 //System.out.println(
4918 // "#" + maxNum + ": " + " descr=" + ci.description);
4919 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004920 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004921 TAG, "State=" + top.state + "Idle=" + top.idle
4922 + " app=" + top.app
4923 + " thr=" + (top.app != null ? top.app.thread : null));
4924 if (top.state == ActivityState.RESUMED
4925 || top.state == ActivityState.PAUSING) {
4926 if (top.idle && top.app != null
4927 && top.app.thread != null) {
4928 topRecord = top;
4929 topThumbnail = top.app.thread;
4930 } else {
4931 top.thumbnailNeeded = true;
4932 }
4933 }
4934 if (pending == null) {
4935 pending = new PendingThumbnailsRecord(receiver);
4936 }
4937 pending.pendingRecords.add(top);
4938 }
4939 list.add(ci);
4940 maxNum--;
4941 top = null;
4942 }
4943 }
4944
4945 if (pending != null) {
4946 mPendingThumbnails.add(pending);
4947 }
4948 }
4949
Joe Onorato8a9b2202010-02-26 18:56:32 -08004950 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004951
4952 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004953 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004954 try {
4955 topThumbnail.requestThumbnail(topRecord);
4956 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004957 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004958 sendPendingThumbnail(null, topRecord, null, null, true);
4959 }
4960 }
4961
4962 if (pending == null && receiver != null) {
4963 // In this case all thumbnails were available and the client
4964 // is being asked to be told when the remaining ones come in...
4965 // which is unusually, since the top-most currently running
4966 // activity should never have a canned thumbnail! Oh well.
4967 try {
4968 receiver.finished();
4969 } catch (RemoteException ex) {
4970 }
4971 }
4972
4973 return list;
4974 }
4975
4976 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
4977 int flags) {
4978 synchronized (this) {
4979 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
4980 "getRecentTasks()");
4981
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004982 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07004983
Dianne Hackbornd2835932010-12-13 16:28:46 -08004984 ActivityRecord resumed = mMainStack.mResumedActivity;
4985
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004986 final int N = mRecentTasks.size();
4987 ArrayList<ActivityManager.RecentTaskInfo> res
4988 = new ArrayList<ActivityManager.RecentTaskInfo>(
4989 maxNum < N ? maxNum : N);
4990 for (int i=0; i<N && maxNum > 0; i++) {
4991 TaskRecord tr = mRecentTasks.get(i);
4992 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
4993 || (tr.intent == null)
4994 || ((tr.intent.getFlags()
4995 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
4996 ActivityManager.RecentTaskInfo rti
4997 = new ActivityManager.RecentTaskInfo();
4998 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
Dianne Hackbornd94df452011-02-16 18:53:31 -08004999 rti.persistentId = tr.taskId;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005000 rti.baseIntent = new Intent(
5001 tr.intent != null ? tr.intent : tr.affinityIntent);
5002 rti.origActivity = tr.origActivity;
Dianne Hackbornd2835932010-12-13 16:28:46 -08005003 rti.description = tr.lastDescription;
5004
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07005005 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
5006 // Check whether this activity is currently available.
5007 try {
5008 if (rti.origActivity != null) {
5009 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
5010 continue;
5011 }
5012 } else if (rti.baseIntent != null) {
5013 if (pm.queryIntentActivities(rti.baseIntent,
5014 null, 0) == null) {
5015 continue;
5016 }
5017 }
5018 } catch (RemoteException e) {
5019 // Will never happen.
5020 }
5021 }
5022
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005023 res.add(rti);
5024 maxNum--;
5025 }
5026 }
5027 return res;
5028 }
5029 }
5030
Dianne Hackbornd94df452011-02-16 18:53:31 -08005031 public Bitmap getTaskThumbnail(int id) {
5032 synchronized (this) {
5033 enforceCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER,
5034 "getTaskThumbnail()");
5035 ActivityRecord resumed = mMainStack.mResumedActivity;
5036 final int N = mRecentTasks.size();
5037 for (int i=0; i<N; i++) {
5038 TaskRecord tr = mRecentTasks.get(i);
5039 if (tr.taskId == id) {
5040 if (resumed != null && resumed.task == tr) {
5041 return resumed.stack.screenshotActivities(resumed);
5042 } else {
5043 return tr.lastThumbnail;
5044 }
5045 }
5046 }
5047 }
5048 return null;
5049 }
5050
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005051 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
5052 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005053 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005054 TaskRecord jt = startTask;
5055
5056 // First look backwards
5057 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005058 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005059 if (r.task != jt) {
5060 jt = r.task;
5061 if (affinity.equals(jt.affinity)) {
5062 return j;
5063 }
5064 }
5065 }
5066
5067 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005068 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005069 jt = startTask;
5070 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005071 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005072 if (r.task != jt) {
5073 if (affinity.equals(jt.affinity)) {
5074 return j;
5075 }
5076 jt = r.task;
5077 }
5078 }
5079
5080 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005081 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005082 return N-1;
5083 }
5084
5085 return -1;
5086 }
5087
5088 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005089 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005090 */
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005091 public void moveTaskToFront(int task, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005092 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5093 "moveTaskToFront()");
5094
5095 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005096 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5097 Binder.getCallingUid(), "Task to front")) {
5098 return;
5099 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005100 final long origId = Binder.clearCallingIdentity();
5101 try {
5102 int N = mRecentTasks.size();
5103 for (int i=0; i<N; i++) {
5104 TaskRecord tr = mRecentTasks.get(i);
5105 if (tr.taskId == task) {
Dianne Hackbornd94df452011-02-16 18:53:31 -08005106 if ((flags&ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
5107 mMainStack.mUserLeaving = true;
5108 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005109 if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
5110 // Caller wants the home activity moved with it. To accomplish this,
5111 // we'll just move the home task to the top first.
5112 mMainStack.moveHomeToFrontLocked();
5113 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005114 mMainStack.moveTaskToFrontLocked(tr, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005115 return;
5116 }
5117 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005118 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
5119 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005120 if (hr.task.taskId == task) {
Dianne Hackbornd94df452011-02-16 18:53:31 -08005121 if ((flags&ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
5122 mMainStack.mUserLeaving = true;
5123 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005124 if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
5125 // Caller wants the home activity moved with it. To accomplish this,
5126 // we'll just move the home task to the top first.
5127 mMainStack.moveHomeToFrontLocked();
5128 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005129 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005130 return;
5131 }
5132 }
5133 } finally {
5134 Binder.restoreCallingIdentity(origId);
5135 }
5136 }
5137 }
5138
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005139 public void moveTaskToBack(int task) {
5140 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5141 "moveTaskToBack()");
5142
5143 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005144 if (mMainStack.mResumedActivity != null
5145 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005146 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5147 Binder.getCallingUid(), "Task to back")) {
5148 return;
5149 }
5150 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005151 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005152 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005153 Binder.restoreCallingIdentity(origId);
5154 }
5155 }
5156
5157 /**
5158 * Moves an activity, and all of the other activities within the same task, to the bottom
5159 * of the history stack. The activity's order within the task is unchanged.
5160 *
5161 * @param token A reference to the activity we wish to move
5162 * @param nonRoot If false then this only works if the activity is the root
5163 * of a task; if true it will work for any activity in a task.
5164 * @return Returns true if the move completed, false if not.
5165 */
5166 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
5167 synchronized(this) {
5168 final long origId = Binder.clearCallingIdentity();
5169 int taskId = getTaskForActivityLocked(token, !nonRoot);
5170 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005171 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005172 }
5173 Binder.restoreCallingIdentity(origId);
5174 }
5175 return false;
5176 }
5177
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005178 public void moveTaskBackwards(int task) {
5179 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5180 "moveTaskBackwards()");
5181
5182 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005183 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5184 Binder.getCallingUid(), "Task backwards")) {
5185 return;
5186 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005187 final long origId = Binder.clearCallingIdentity();
5188 moveTaskBackwardsLocked(task);
5189 Binder.restoreCallingIdentity(origId);
5190 }
5191 }
5192
5193 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005194 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005195 }
5196
5197 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
5198 synchronized(this) {
5199 return getTaskForActivityLocked(token, onlyRoot);
5200 }
5201 }
5202
5203 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005204 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005205 TaskRecord lastTask = null;
5206 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005207 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005208 if (r == token) {
5209 if (!onlyRoot || lastTask != r.task) {
5210 return r.task.taskId;
5211 }
5212 return -1;
5213 }
5214 lastTask = r.task;
5215 }
5216
5217 return -1;
5218 }
5219
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005220 public void finishOtherInstances(IBinder token, ComponentName className) {
5221 synchronized(this) {
5222 final long origId = Binder.clearCallingIdentity();
5223
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005224 int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005225 TaskRecord lastTask = null;
5226 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005227 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005228 if (r.realActivity.equals(className)
5229 && r != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005230 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005231 null, "others")) {
5232 i--;
5233 N--;
5234 }
5235 }
5236 lastTask = r.task;
5237 }
5238
5239 Binder.restoreCallingIdentity(origId);
5240 }
5241 }
5242
5243 // =========================================================
5244 // THUMBNAILS
5245 // =========================================================
5246
5247 public void reportThumbnail(IBinder token,
5248 Bitmap thumbnail, CharSequence description) {
5249 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
5250 final long origId = Binder.clearCallingIdentity();
5251 sendPendingThumbnail(null, token, thumbnail, description, true);
5252 Binder.restoreCallingIdentity(origId);
5253 }
5254
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005255 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005256 Bitmap thumbnail, CharSequence description, boolean always) {
5257 TaskRecord task = null;
5258 ArrayList receivers = null;
5259
5260 //System.out.println("Send pending thumbnail: " + r);
5261
5262 synchronized(this) {
5263 if (r == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005264 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005265 if (index < 0) {
5266 return;
5267 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005268 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005269 }
5270 if (thumbnail == null) {
5271 thumbnail = r.thumbnail;
5272 description = r.description;
5273 }
5274 if (thumbnail == null && !always) {
5275 // If there is no thumbnail, and this entry is not actually
5276 // going away, then abort for now and pick up the next
5277 // thumbnail we get.
5278 return;
5279 }
5280 task = r.task;
5281
5282 int N = mPendingThumbnails.size();
5283 int i=0;
5284 while (i<N) {
5285 PendingThumbnailsRecord pr =
5286 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
5287 //System.out.println("Looking in " + pr.pendingRecords);
5288 if (pr.pendingRecords.remove(r)) {
5289 if (receivers == null) {
5290 receivers = new ArrayList();
5291 }
5292 receivers.add(pr);
5293 if (pr.pendingRecords.size() == 0) {
5294 pr.finished = true;
5295 mPendingThumbnails.remove(i);
5296 N--;
5297 continue;
5298 }
5299 }
5300 i++;
5301 }
5302 }
5303
5304 if (receivers != null) {
5305 final int N = receivers.size();
5306 for (int i=0; i<N; i++) {
5307 try {
5308 PendingThumbnailsRecord pr =
5309 (PendingThumbnailsRecord)receivers.get(i);
5310 pr.receiver.newThumbnail(
5311 task != null ? task.taskId : -1, thumbnail, description);
5312 if (pr.finished) {
5313 pr.receiver.finished();
5314 }
5315 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005316 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005317 }
5318 }
5319 }
5320 }
5321
5322 // =========================================================
5323 // CONTENT PROVIDERS
5324 // =========================================================
5325
5326 private final List generateApplicationProvidersLocked(ProcessRecord app) {
5327 List providers = null;
5328 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005329 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005330 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005331 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005332 } catch (RemoteException ex) {
5333 }
5334 if (providers != null) {
5335 final int N = providers.size();
5336 for (int i=0; i<N; i++) {
5337 ProviderInfo cpi =
5338 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005339 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005340 if (cpr == null) {
5341 cpr = new ContentProviderRecord(cpi, app.info);
5342 mProvidersByClass.put(cpi.name, cpr);
5343 }
5344 app.pubProviders.put(cpi.name, cpr);
5345 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005346 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005347 }
5348 }
5349 return providers;
5350 }
5351
5352 private final String checkContentProviderPermissionLocked(
Dianne Hackbornb424b632010-08-18 15:59:05 -07005353 ProviderInfo cpi, ProcessRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005354 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
5355 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
5356 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005357 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005358 == PackageManager.PERMISSION_GRANTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005359 return null;
5360 }
5361 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005362 cpi.applicationInfo.uid, cpi.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005363 == PackageManager.PERMISSION_GRANTED) {
5364 return null;
5365 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005366
5367 PathPermission[] pps = cpi.pathPermissions;
5368 if (pps != null) {
5369 int i = pps.length;
5370 while (i > 0) {
5371 i--;
5372 PathPermission pp = pps[i];
5373 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005374 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005375 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005376 return null;
5377 }
5378 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005379 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005380 == PackageManager.PERMISSION_GRANTED) {
5381 return null;
5382 }
5383 }
5384 }
5385
Dianne Hackbornb424b632010-08-18 15:59:05 -07005386 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
5387 if (perms != null) {
5388 for (Map.Entry<Uri, UriPermission> uri : perms.entrySet()) {
5389 if (uri.getKey().getAuthority().equals(cpi.authority)) {
5390 return null;
5391 }
5392 }
5393 }
5394
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005395 String msg;
5396 if (!cpi.exported) {
5397 msg = "Permission Denial: opening provider " + cpi.name
5398 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5399 + ", uid=" + callingUid + ") that is not exported from uid "
5400 + cpi.applicationInfo.uid;
5401 } else {
5402 msg = "Permission Denial: opening provider " + cpi.name
5403 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5404 + ", uid=" + callingUid + ") requires "
5405 + cpi.readPermission + " or " + cpi.writePermission;
5406 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005407 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005408 return msg;
5409 }
5410
5411 private final ContentProviderHolder getContentProviderImpl(
5412 IApplicationThread caller, String name) {
5413 ContentProviderRecord cpr;
5414 ProviderInfo cpi = null;
5415
5416 synchronized(this) {
5417 ProcessRecord r = null;
5418 if (caller != null) {
5419 r = getRecordForAppLocked(caller);
5420 if (r == null) {
5421 throw new SecurityException(
5422 "Unable to find app for caller " + caller
5423 + " (pid=" + Binder.getCallingPid()
5424 + ") when getting content provider " + name);
5425 }
5426 }
5427
5428 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07005429 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005430 if (cpr != null) {
5431 cpi = cpr.info;
Dianne Hackbornb424b632010-08-18 15:59:05 -07005432 String msg;
5433 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5434 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005435 }
5436
5437 if (r != null && cpr.canRunHere(r)) {
5438 // This provider has been published or is in the process
5439 // of being published... but it is also allowed to run
5440 // in the caller's process, so don't make a connection
5441 // and just let the caller instantiate its own instance.
5442 if (cpr.provider != null) {
5443 // don't give caller the provider object, it needs
5444 // to make its own.
5445 cpr = new ContentProviderRecord(cpr);
5446 }
5447 return cpr;
5448 }
5449
5450 final long origId = Binder.clearCallingIdentity();
5451
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005452 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005453 // return it right away.
5454 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005455 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005456 "Adding provider requested by "
5457 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005458 + cpr.info.processName);
5459 Integer cnt = r.conProviders.get(cpr);
5460 if (cnt == null) {
5461 r.conProviders.put(cpr, new Integer(1));
5462 } else {
5463 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5464 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005465 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07005466 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
5467 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07005468 // make sure to count it as being accessed and thus
5469 // back up on the LRU list. This is good because
5470 // content providers are often expensive to start.
5471 updateLruProcessLocked(cpr.app, false, true);
5472 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07005473 } else {
5474 cpr.externals++;
5475 }
5476
5477 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005478 updateOomAdjLocked(cpr.app);
5479 }
5480
5481 Binder.restoreCallingIdentity(origId);
5482
5483 } else {
5484 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005485 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005486 resolveContentProvider(name,
5487 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005488 } catch (RemoteException ex) {
5489 }
5490 if (cpi == null) {
5491 return null;
5492 }
5493
Dianne Hackbornb424b632010-08-18 15:59:05 -07005494 String msg;
5495 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5496 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005497 }
5498
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07005499 if (!mProcessesReady && !mDidUpdate && !mWaitingUpdate
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005500 && !cpi.processName.equals("system")) {
5501 // If this content provider does not run in the system
5502 // process, and the system is not yet ready to run other
5503 // processes, then fail fast instead of hanging.
5504 throw new IllegalArgumentException(
5505 "Attempt to launch content provider before system ready");
5506 }
5507
Dianne Hackborn860755f2010-06-03 18:47:52 -07005508 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005509 final boolean firstClass = cpr == null;
5510 if (firstClass) {
5511 try {
5512 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005513 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005514 getApplicationInfo(
5515 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005516 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005517 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005518 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005519 + cpi.name);
5520 return null;
5521 }
5522 cpr = new ContentProviderRecord(cpi, ai);
5523 } catch (RemoteException ex) {
5524 // pm is in same process, this will never happen.
5525 }
5526 }
5527
5528 if (r != null && cpr.canRunHere(r)) {
5529 // If this is a multiprocess provider, then just return its
5530 // info and allow the caller to instantiate it. Only do
5531 // this if the provider is the same user as the caller's
5532 // process, or can run as root (so can be in any process).
5533 return cpr;
5534 }
5535
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005536 if (DEBUG_PROVIDER) {
5537 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08005538 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005539 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005540 }
5541
5542 // This is single process, and our app is now connecting to it.
5543 // See if we are already in the process of launching this
5544 // provider.
5545 final int N = mLaunchingProviders.size();
5546 int i;
5547 for (i=0; i<N; i++) {
5548 if (mLaunchingProviders.get(i) == cpr) {
5549 break;
5550 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005551 }
5552
5553 // If the provider is not already being launched, then get it
5554 // started.
5555 if (i >= N) {
5556 final long origId = Binder.clearCallingIdentity();
Dianne Hackborne7f97212011-02-24 14:40:20 -08005557
5558 try {
5559 // Content provider is now in use, its package can't be stopped.
5560 try {
5561 AppGlobals.getPackageManager().setPackageStoppedState(
5562 cpr.appInfo.packageName, false);
5563 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08005564 } catch (IllegalArgumentException e) {
5565 Slog.w(TAG, "Failed trying to unstop package "
5566 + cpr.appInfo.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08005567 }
5568
5569 ProcessRecord proc = startProcessLocked(cpi.processName,
5570 cpr.appInfo, false, 0, "content provider",
5571 new ComponentName(cpi.applicationInfo.packageName,
5572 cpi.name), false);
5573 if (proc == null) {
5574 Slog.w(TAG, "Unable to launch app "
5575 + cpi.applicationInfo.packageName + "/"
5576 + cpi.applicationInfo.uid + " for provider "
5577 + name + ": process is bad");
5578 return null;
5579 }
5580 cpr.launchingApp = proc;
5581 mLaunchingProviders.add(cpr);
5582 } finally {
5583 Binder.restoreCallingIdentity(origId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005584 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005585 }
5586
5587 // Make sure the provider is published (the same provider class
5588 // may be published under multiple names).
5589 if (firstClass) {
5590 mProvidersByClass.put(cpi.name, cpr);
5591 }
5592 mProvidersByName.put(name, cpr);
5593
5594 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005595 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005596 "Adding provider requested by "
5597 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005598 + cpr.info.processName);
5599 Integer cnt = r.conProviders.get(cpr);
5600 if (cnt == null) {
5601 r.conProviders.put(cpr, new Integer(1));
5602 } else {
5603 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5604 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005605 cpr.clients.add(r);
5606 } else {
5607 cpr.externals++;
5608 }
5609 }
5610 }
5611
5612 // Wait for the provider to be published...
5613 synchronized (cpr) {
5614 while (cpr.provider == null) {
5615 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005616 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005617 + cpi.applicationInfo.packageName + "/"
5618 + cpi.applicationInfo.uid + " for provider "
5619 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005620 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005621 cpi.applicationInfo.packageName,
5622 cpi.applicationInfo.uid, name);
5623 return null;
5624 }
5625 try {
5626 cpr.wait();
5627 } catch (InterruptedException ex) {
5628 }
5629 }
5630 }
5631 return cpr;
5632 }
5633
5634 public final ContentProviderHolder getContentProvider(
5635 IApplicationThread caller, String name) {
5636 if (caller == null) {
5637 String msg = "null IApplicationThread when getting content provider "
5638 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005639 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005640 throw new SecurityException(msg);
5641 }
5642
5643 return getContentProviderImpl(caller, name);
5644 }
5645
5646 private ContentProviderHolder getContentProviderExternal(String name) {
5647 return getContentProviderImpl(null, name);
5648 }
5649
5650 /**
5651 * Drop a content provider from a ProcessRecord's bookkeeping
5652 * @param cpr
5653 */
5654 public void removeContentProvider(IApplicationThread caller, String name) {
5655 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005656 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005657 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005658 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005659 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005660 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005661 return;
5662 }
5663 final ProcessRecord r = getRecordForAppLocked(caller);
5664 if (r == null) {
5665 throw new SecurityException(
5666 "Unable to find app for caller " + caller +
5667 " when removing content provider " + name);
5668 }
5669 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005670 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005671 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005672 + r.info.processName + " from process "
5673 + localCpr.appInfo.processName);
5674 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005675 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08005676 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005677 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005678 return;
5679 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005680 Integer cnt = r.conProviders.get(localCpr);
5681 if (cnt == null || cnt.intValue() <= 1) {
5682 localCpr.clients.remove(r);
5683 r.conProviders.remove(localCpr);
5684 } else {
5685 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
5686 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005687 }
5688 updateOomAdjLocked();
5689 }
5690 }
5691
5692 private void removeContentProviderExternal(String name) {
5693 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005694 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005695 if(cpr == null) {
5696 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005697 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005698 return;
5699 }
5700
5701 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005702 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005703 localCpr.externals--;
5704 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005705 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005706 }
5707 updateOomAdjLocked();
5708 }
5709 }
5710
5711 public final void publishContentProviders(IApplicationThread caller,
5712 List<ContentProviderHolder> providers) {
5713 if (providers == null) {
5714 return;
5715 }
5716
5717 synchronized(this) {
5718 final ProcessRecord r = getRecordForAppLocked(caller);
5719 if (r == null) {
5720 throw new SecurityException(
5721 "Unable to find app for caller " + caller
5722 + " (pid=" + Binder.getCallingPid()
5723 + ") when publishing content providers");
5724 }
5725
5726 final long origId = Binder.clearCallingIdentity();
5727
5728 final int N = providers.size();
5729 for (int i=0; i<N; i++) {
5730 ContentProviderHolder src = providers.get(i);
5731 if (src == null || src.info == null || src.provider == null) {
5732 continue;
5733 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005734 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005735 if (dst != null) {
5736 mProvidersByClass.put(dst.info.name, dst);
5737 String names[] = dst.info.authority.split(";");
5738 for (int j = 0; j < names.length; j++) {
5739 mProvidersByName.put(names[j], dst);
5740 }
5741
5742 int NL = mLaunchingProviders.size();
5743 int j;
5744 for (j=0; j<NL; j++) {
5745 if (mLaunchingProviders.get(j) == dst) {
5746 mLaunchingProviders.remove(j);
5747 j--;
5748 NL--;
5749 }
5750 }
5751 synchronized (dst) {
5752 dst.provider = src.provider;
5753 dst.app = r;
5754 dst.notifyAll();
5755 }
5756 updateOomAdjLocked(r);
5757 }
5758 }
5759
5760 Binder.restoreCallingIdentity(origId);
5761 }
5762 }
5763
5764 public static final void installSystemProviders() {
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005765 List providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06005766 synchronized (mSelf) {
5767 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
5768 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005769 if (providers != null) {
5770 for (int i=providers.size()-1; i>=0; i--) {
5771 ProviderInfo pi = (ProviderInfo)providers.get(i);
5772 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5773 Slog.w(TAG, "Not installing system proc provider " + pi.name
5774 + ": not system .apk");
5775 providers.remove(i);
5776 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005777 }
5778 }
5779 }
Josh Bartel2ecce342010-02-25 10:55:48 -06005780 if (providers != null) {
5781 mSystemThread.installSystemProviders(providers);
5782 }
Svetoslav Ganov54d068e2011-03-02 12:58:40 -08005783
5784 mSelf.mCoreSettingsObserver = new CoreSettingsObserver(mSelf);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005785 }
5786
Dianne Hackborncca1f0e2010-09-26 18:34:53 -07005787 /**
5788 * Allows app to retrieve the MIME type of a URI without having permission
5789 * to access its content provider.
5790 *
5791 * CTS tests for this functionality can be run with "runtest cts-appsecurity".
5792 *
5793 * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
5794 * src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
5795 */
5796 public String getProviderMimeType(Uri uri) {
5797 final String name = uri.getAuthority();
5798 final long ident = Binder.clearCallingIdentity();
5799 ContentProviderHolder holder = null;
5800
5801 try {
5802 holder = getContentProviderExternal(name);
5803 if (holder != null) {
5804 return holder.provider.getType(uri);
5805 }
5806 } catch (RemoteException e) {
5807 Log.w(TAG, "Content provider dead retrieving " + uri, e);
5808 return null;
5809 } finally {
5810 if (holder != null) {
5811 removeContentProviderExternal(name);
5812 }
5813 Binder.restoreCallingIdentity(ident);
5814 }
5815
5816 return null;
5817 }
5818
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005819 // =========================================================
5820 // GLOBAL MANAGEMENT
5821 // =========================================================
5822
5823 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
5824 ApplicationInfo info, String customProcess) {
5825 String proc = customProcess != null ? customProcess : info.processName;
5826 BatteryStatsImpl.Uid.Proc ps = null;
5827 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5828 synchronized (stats) {
5829 ps = stats.getProcessStatsLocked(info.uid, proc);
5830 }
5831 return new ProcessRecord(ps, thread, info, proc);
5832 }
5833
5834 final ProcessRecord addAppLocked(ApplicationInfo info) {
5835 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
5836
5837 if (app == null) {
5838 app = newProcessRecordLocked(null, info, null);
5839 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005840 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005841 }
5842
Dianne Hackborne7f97212011-02-24 14:40:20 -08005843 // This package really, really can not be stopped.
5844 try {
5845 AppGlobals.getPackageManager().setPackageStoppedState(
5846 info.packageName, false);
5847 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08005848 } catch (IllegalArgumentException e) {
5849 Slog.w(TAG, "Failed trying to unstop package "
5850 + info.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08005851 }
5852
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005853 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
5854 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
5855 app.persistent = true;
5856 app.maxAdj = CORE_SERVER_ADJ;
5857 }
5858 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
5859 mPersistentStartingProcesses.add(app);
5860 startProcessLocked(app, "added application", app.processName);
5861 }
5862
5863 return app;
5864 }
5865
5866 public void unhandledBack() {
5867 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
5868 "unhandledBack()");
5869
5870 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005871 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08005872 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005873 TAG, "Performing unhandledBack(): stack size = " + count);
5874 if (count > 1) {
5875 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005876 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005877 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
5878 Binder.restoreCallingIdentity(origId);
5879 }
5880 }
5881 }
5882
5883 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
5884 String name = uri.getAuthority();
5885 ContentProviderHolder cph = getContentProviderExternal(name);
5886 ParcelFileDescriptor pfd = null;
5887 if (cph != null) {
5888 // We record the binder invoker's uid in thread-local storage before
5889 // going to the content provider to open the file. Later, in the code
5890 // that handles all permissions checks, we look for this uid and use
5891 // that rather than the Activity Manager's own uid. The effect is that
5892 // we do the check against the caller's permissions even though it looks
5893 // to the content provider like the Activity Manager itself is making
5894 // the request.
5895 sCallerIdentity.set(new Identity(
5896 Binder.getCallingPid(), Binder.getCallingUid()));
5897 try {
5898 pfd = cph.provider.openFile(uri, "r");
5899 } catch (FileNotFoundException e) {
5900 // do nothing; pfd will be returned null
5901 } finally {
5902 // Ensure that whatever happens, we clean up the identity state
5903 sCallerIdentity.remove();
5904 }
5905
5906 // We've got the fd now, so we're done with the provider.
5907 removeContentProviderExternal(name);
5908 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005909 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005910 }
5911 return pfd;
5912 }
5913
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005914 // Actually is sleeping or shutting down or whatever else in the future
5915 // is an inactive state.
5916 public boolean isSleeping() {
5917 return mSleeping || mShuttingDown;
5918 }
5919
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005920 public void goingToSleep() {
5921 synchronized(this) {
5922 mSleeping = true;
5923 mWindowManager.setEventDispatching(false);
5924
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005925 mMainStack.stopIfSleepingLocked();
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005926
5927 // Initialize the wake times of all processes.
Dianne Hackborn287952c2010-09-22 22:34:31 -07005928 checkExcessivePowerUsageLocked(false);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07005929 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
5930 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07005931 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005932 }
5933 }
5934
Dianne Hackborn55280a92009-05-07 15:53:46 -07005935 public boolean shutdown(int timeout) {
5936 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
5937 != PackageManager.PERMISSION_GRANTED) {
5938 throw new SecurityException("Requires permission "
5939 + android.Manifest.permission.SHUTDOWN);
5940 }
5941
5942 boolean timedout = false;
5943
5944 synchronized(this) {
5945 mShuttingDown = true;
5946 mWindowManager.setEventDispatching(false);
5947
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005948 if (mMainStack.mResumedActivity != null) {
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005949 mMainStack.stopIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07005950 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005951 while (mMainStack.mResumedActivity != null
5952 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07005953 long delay = endTime - System.currentTimeMillis();
5954 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005955 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07005956 timedout = true;
5957 break;
5958 }
5959 try {
5960 this.wait();
5961 } catch (InterruptedException e) {
5962 }
5963 }
5964 }
5965 }
5966
5967 mUsageStatsService.shutdown();
5968 mBatteryStatsService.shutdown();
5969
5970 return timedout;
5971 }
5972
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005973 public final void activitySlept(IBinder token) {
5974 if (localLOGV) Slog.v(
5975 TAG, "Activity slept: token=" + token);
5976
5977 ActivityRecord r = null;
5978
5979 final long origId = Binder.clearCallingIdentity();
5980
5981 synchronized (this) {
5982 int index = mMainStack.indexOfTokenLocked(token);
5983 if (index >= 0) {
5984 r = (ActivityRecord)mMainStack.mHistory.get(index);
5985 mMainStack.activitySleptLocked(r);
5986 }
5987 }
5988
5989 Binder.restoreCallingIdentity(origId);
5990 }
5991
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005992 public void wakingUp() {
5993 synchronized(this) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005994 mWindowManager.setEventDispatching(true);
5995 mSleeping = false;
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08005996 mMainStack.awakeFromSleepingLocked();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005997 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005998 }
5999 }
6000
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006001 public void stopAppSwitches() {
6002 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
6003 != PackageManager.PERMISSION_GRANTED) {
6004 throw new SecurityException("Requires permission "
6005 + android.Manifest.permission.STOP_APP_SWITCHES);
6006 }
6007
6008 synchronized(this) {
6009 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
6010 + APP_SWITCH_DELAY_TIME;
6011 mDidAppSwitch = false;
6012 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
6013 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
6014 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
6015 }
6016 }
6017
6018 public void resumeAppSwitches() {
6019 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
6020 != PackageManager.PERMISSION_GRANTED) {
6021 throw new SecurityException("Requires permission "
6022 + android.Manifest.permission.STOP_APP_SWITCHES);
6023 }
6024
6025 synchronized(this) {
6026 // Note that we don't execute any pending app switches... we will
6027 // let those wait until either the timeout, or the next start
6028 // activity request.
6029 mAppSwitchesAllowedTime = 0;
6030 }
6031 }
6032
6033 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
6034 String name) {
6035 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
6036 return true;
6037 }
6038
6039 final int perm = checkComponentPermission(
6040 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08006041 callingUid, -1, true);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006042 if (perm == PackageManager.PERMISSION_GRANTED) {
6043 return true;
6044 }
6045
Joe Onorato8a9b2202010-02-26 18:56:32 -08006046 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006047 return false;
6048 }
6049
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006050 public void setDebugApp(String packageName, boolean waitForDebugger,
6051 boolean persistent) {
6052 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
6053 "setDebugApp()");
6054
6055 // Note that this is not really thread safe if there are multiple
6056 // callers into it at the same time, but that's not a situation we
6057 // care about.
6058 if (persistent) {
6059 final ContentResolver resolver = mContext.getContentResolver();
6060 Settings.System.putString(
6061 resolver, Settings.System.DEBUG_APP,
6062 packageName);
6063 Settings.System.putInt(
6064 resolver, Settings.System.WAIT_FOR_DEBUGGER,
6065 waitForDebugger ? 1 : 0);
6066 }
6067
6068 synchronized (this) {
6069 if (!persistent) {
6070 mOrigDebugApp = mDebugApp;
6071 mOrigWaitForDebugger = mWaitForDebugger;
6072 }
6073 mDebugApp = packageName;
6074 mWaitForDebugger = waitForDebugger;
6075 mDebugTransient = !persistent;
6076 if (packageName != null) {
6077 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006078 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006079 Binder.restoreCallingIdentity(origId);
6080 }
6081 }
6082 }
6083
6084 public void setAlwaysFinish(boolean enabled) {
6085 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
6086 "setAlwaysFinish()");
6087
6088 Settings.System.putInt(
6089 mContext.getContentResolver(),
6090 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
6091
6092 synchronized (this) {
6093 mAlwaysFinishActivities = enabled;
6094 }
6095 }
6096
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006097 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006098 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006099 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006100 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006101 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006102 }
6103 }
6104
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08006105 public boolean isUserAMonkey() {
6106 // For now the fact that there is a controller implies
6107 // we have a monkey.
6108 synchronized (this) {
6109 return mController != null;
6110 }
6111 }
6112
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006113 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06006114 synchronized (this) {
6115 mWatchers.register(watcher);
6116 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006117 }
6118
6119 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06006120 synchronized (this) {
6121 mWatchers.unregister(watcher);
6122 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006123 }
6124
Daniel Sandler69a48172010-06-23 16:29:36 -04006125 public void setImmersive(IBinder token, boolean immersive) {
6126 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006127 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04006128 if (index < 0) {
6129 throw new IllegalArgumentException();
6130 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006131 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04006132 r.immersive = immersive;
6133 }
6134 }
6135
6136 public boolean isImmersive(IBinder token) {
6137 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006138 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04006139 if (index < 0) {
6140 throw new IllegalArgumentException();
6141 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006142 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04006143 return r.immersive;
6144 }
6145 }
6146
6147 public boolean isTopActivityImmersive() {
6148 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006149 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Daniel Sandler69a48172010-06-23 16:29:36 -04006150 return (r != null) ? r.immersive : false;
6151 }
6152 }
6153
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006154 public final void enterSafeMode() {
6155 synchronized(this) {
6156 // It only makes sense to do this before the system is ready
6157 // and started launching other packages.
6158 if (!mSystemReady) {
6159 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006160 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006161 } catch (RemoteException e) {
6162 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006163 }
6164 }
6165 }
6166
Jeff Brownb09abc12011-01-13 21:08:27 -08006167 public final void showSafeModeOverlay() {
6168 View v = LayoutInflater.from(mContext).inflate(
6169 com.android.internal.R.layout.safe_mode, null);
6170 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
6171 lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
6172 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
6173 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
6174 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
6175 lp.format = v.getBackground().getOpacity();
6176 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
6177 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
6178 ((WindowManager)mContext.getSystemService(
6179 Context.WINDOW_SERVICE)).addView(v, lp);
6180 }
6181
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006182 public void noteWakeupAlarm(IIntentSender sender) {
6183 if (!(sender instanceof PendingIntentRecord)) {
6184 return;
6185 }
6186 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
6187 synchronized (stats) {
6188 if (mBatteryStatsService.isOnBattery()) {
6189 mBatteryStatsService.enforceCallingPermission();
6190 PendingIntentRecord rec = (PendingIntentRecord)sender;
6191 int MY_UID = Binder.getCallingUid();
6192 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
6193 BatteryStatsImpl.Uid.Pkg pkg =
6194 stats.getPackageStatsLocked(uid, rec.key.packageName);
6195 pkg.incWakeupsLocked();
6196 }
6197 }
6198 }
6199
Dianne Hackborn64825172011-03-02 21:32:58 -08006200 public boolean killPids(int[] pids, String pReason, boolean secure) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006201 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006202 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006203 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006204 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006205 // XXX Note: don't acquire main activity lock here, because the window
6206 // manager calls in with its locks held.
6207
6208 boolean killed = false;
6209 synchronized (mPidsSelfLocked) {
6210 int[] types = new int[pids.length];
6211 int worstType = 0;
6212 for (int i=0; i<pids.length; i++) {
6213 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6214 if (proc != null) {
6215 int type = proc.setAdj;
6216 types[i] = type;
6217 if (type > worstType) {
6218 worstType = type;
6219 }
6220 }
6221 }
6222
Dianne Hackborn64825172011-03-02 21:32:58 -08006223 // If the worst oom_adj is somewhere in the hidden proc LRU range,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006224 // then constrain it so we will kill all hidden procs.
6225 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
6226 worstType = HIDDEN_APP_MIN_ADJ;
6227 }
Dianne Hackborn64825172011-03-02 21:32:58 -08006228
6229 // If this is not a secure call, don't let it kill processes that
6230 // are important.
6231 if (!secure && worstType < SECONDARY_SERVER_ADJ) {
6232 worstType = SECONDARY_SERVER_ADJ;
6233 }
6234
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006235 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006236 for (int i=0; i<pids.length; i++) {
6237 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6238 if (proc == null) {
6239 continue;
6240 }
6241 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006242 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07006243 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006244 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
6245 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006246 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006247 proc.killedBackground = true;
6248 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006249 }
6250 }
6251 }
6252 return killed;
6253 }
6254
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006255 public final void startRunning(String pkg, String cls, String action,
6256 String data) {
6257 synchronized(this) {
6258 if (mStartRunning) {
6259 return;
6260 }
6261 mStartRunning = true;
6262 mTopComponent = pkg != null && cls != null
6263 ? new ComponentName(pkg, cls) : null;
6264 mTopAction = action != null ? action : Intent.ACTION_MAIN;
6265 mTopData = data;
6266 if (!mSystemReady) {
6267 return;
6268 }
6269 }
6270
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006271 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006272 }
6273
6274 private void retrieveSettings() {
6275 final ContentResolver resolver = mContext.getContentResolver();
6276 String debugApp = Settings.System.getString(
6277 resolver, Settings.System.DEBUG_APP);
6278 boolean waitForDebugger = Settings.System.getInt(
6279 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
6280 boolean alwaysFinishActivities = Settings.System.getInt(
6281 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
6282
6283 Configuration configuration = new Configuration();
6284 Settings.System.getConfiguration(resolver, configuration);
6285
6286 synchronized (this) {
6287 mDebugApp = mOrigDebugApp = debugApp;
6288 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
6289 mAlwaysFinishActivities = alwaysFinishActivities;
6290 // This happens before any activities are started, so we can
6291 // change mConfiguration in-place.
6292 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08006293 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006294 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006295 }
6296 }
6297
6298 public boolean testIsSystemReady() {
6299 // no need to synchronize(this) just to read & return the value
6300 return mSystemReady;
6301 }
6302
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006303 private static File getCalledPreBootReceiversFile() {
6304 File dataDir = Environment.getDataDirectory();
6305 File systemDir = new File(dataDir, "system");
6306 File fname = new File(systemDir, "called_pre_boots.dat");
6307 return fname;
6308 }
6309
6310 private static ArrayList<ComponentName> readLastDonePreBootReceivers() {
6311 ArrayList<ComponentName> lastDoneReceivers = new ArrayList<ComponentName>();
6312 File file = getCalledPreBootReceiversFile();
6313 FileInputStream fis = null;
6314 try {
6315 fis = new FileInputStream(file);
6316 DataInputStream dis = new DataInputStream(new BufferedInputStream(fis, 2048));
6317 int vers = dis.readInt();
6318 String codename = dis.readUTF();
6319 if (vers == android.os.Build.VERSION.SDK_INT
6320 && codename.equals(android.os.Build.VERSION.CODENAME)) {
6321 int num = dis.readInt();
6322 while (num > 0) {
6323 num--;
6324 String pkg = dis.readUTF();
6325 String cls = dis.readUTF();
6326 lastDoneReceivers.add(new ComponentName(pkg, cls));
6327 }
6328 }
6329 } catch (FileNotFoundException e) {
6330 } catch (IOException e) {
6331 Slog.w(TAG, "Failure reading last done pre-boot receivers", e);
6332 } finally {
6333 if (fis != null) {
6334 try {
6335 fis.close();
6336 } catch (IOException e) {
6337 }
6338 }
6339 }
6340 return lastDoneReceivers;
6341 }
6342
6343 private static void writeLastDonePreBootReceivers(ArrayList<ComponentName> list) {
6344 File file = getCalledPreBootReceiversFile();
6345 FileOutputStream fos = null;
6346 DataOutputStream dos = null;
6347 try {
6348 Slog.i(TAG, "Writing new set of last done pre-boot receivers...");
6349 fos = new FileOutputStream(file);
6350 dos = new DataOutputStream(new BufferedOutputStream(fos, 2048));
6351 dos.writeInt(android.os.Build.VERSION.SDK_INT);
6352 dos.writeUTF(android.os.Build.VERSION.CODENAME);
6353 dos.writeInt(list.size());
6354 for (int i=0; i<list.size(); i++) {
6355 dos.writeUTF(list.get(i).getPackageName());
6356 dos.writeUTF(list.get(i).getClassName());
6357 }
6358 } catch (IOException e) {
6359 Slog.w(TAG, "Failure writing last done pre-boot receivers", e);
6360 file.delete();
6361 } finally {
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07006362 FileUtils.sync(fos);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006363 if (dos != null) {
6364 try {
6365 dos.close();
6366 } catch (IOException e) {
6367 // TODO Auto-generated catch block
6368 e.printStackTrace();
6369 }
6370 }
6371 }
6372 }
6373
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006374 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006375 // In the simulator, startRunning will never have been called, which
6376 // normally sets a few crucial variables. Do it here instead.
6377 if (!Process.supportsProcesses()) {
6378 mStartRunning = true;
6379 mTopAction = Intent.ACTION_MAIN;
6380 }
6381
6382 synchronized(this) {
6383 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006384 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006385 return;
6386 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006387
6388 // Check to see if there are any update receivers to run.
6389 if (!mDidUpdate) {
6390 if (mWaitingUpdate) {
6391 return;
6392 }
6393 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
6394 List<ResolveInfo> ris = null;
6395 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006396 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006397 intent, null, 0);
6398 } catch (RemoteException e) {
6399 }
6400 if (ris != null) {
6401 for (int i=ris.size()-1; i>=0; i--) {
6402 if ((ris.get(i).activityInfo.applicationInfo.flags
6403 &ApplicationInfo.FLAG_SYSTEM) == 0) {
6404 ris.remove(i);
6405 }
6406 }
6407 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006408
6409 ArrayList<ComponentName> lastDoneReceivers = readLastDonePreBootReceivers();
6410
6411 final ArrayList<ComponentName> doneReceivers = new ArrayList<ComponentName>();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006412 for (int i=0; i<ris.size(); i++) {
6413 ActivityInfo ai = ris.get(i).activityInfo;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006414 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6415 if (lastDoneReceivers.contains(comp)) {
6416 ris.remove(i);
6417 i--;
6418 }
6419 }
6420
6421 for (int i=0; i<ris.size(); i++) {
6422 ActivityInfo ai = ris.get(i).activityInfo;
6423 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6424 doneReceivers.add(comp);
6425 intent.setComponent(comp);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006426 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08006427 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006428 finisher = new IIntentReceiver.Stub() {
6429 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07006430 String data, Bundle extras, boolean ordered,
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006431 boolean sticky) {
6432 // The raw IIntentReceiver interface is called
6433 // with the AM lock held, so redispatch to
6434 // execute our code without the lock.
6435 mHandler.post(new Runnable() {
6436 public void run() {
6437 synchronized (ActivityManagerService.this) {
6438 mDidUpdate = true;
6439 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006440 writeLastDonePreBootReceivers(doneReceivers);
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006441 systemReady(goingCallback);
6442 }
6443 });
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006444 }
6445 };
6446 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006447 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006448 broadcastIntentLocked(null, null, intent, null, finisher,
6449 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08006450 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006451 mWaitingUpdate = true;
6452 }
6453 }
6454 }
6455 if (mWaitingUpdate) {
6456 return;
6457 }
6458 mDidUpdate = true;
6459 }
6460
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006461 mSystemReady = true;
6462 if (!mStartRunning) {
6463 return;
6464 }
6465 }
6466
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006467 ArrayList<ProcessRecord> procsToKill = null;
6468 synchronized(mPidsSelfLocked) {
6469 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
6470 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
6471 if (!isAllowedWhileBooting(proc.info)){
6472 if (procsToKill == null) {
6473 procsToKill = new ArrayList<ProcessRecord>();
6474 }
6475 procsToKill.add(proc);
6476 }
6477 }
6478 }
6479
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006480 synchronized(this) {
6481 if (procsToKill != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006482 for (int i=procsToKill.size()-1; i>=0; i--) {
6483 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08006484 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006485 removeProcessLocked(proc, true);
6486 }
6487 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006488
6489 // Now that we have cleaned up any update processes, we
6490 // are ready to start launching real processes and know that
6491 // we won't trample on them any more.
6492 mProcessesReady = true;
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006493 }
6494
Joe Onorato8a9b2202010-02-26 18:56:32 -08006495 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006496 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006497 SystemClock.uptimeMillis());
6498
6499 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006500 // Make sure we have no pre-ready processes sitting around.
6501
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006502 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
6503 ResolveInfo ri = mContext.getPackageManager()
6504 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07006505 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006506 CharSequence errorMsg = null;
6507 if (ri != null) {
6508 ActivityInfo ai = ri.activityInfo;
6509 ApplicationInfo app = ai.applicationInfo;
6510 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
6511 mTopAction = Intent.ACTION_FACTORY_TEST;
6512 mTopData = null;
6513 mTopComponent = new ComponentName(app.packageName,
6514 ai.name);
6515 } else {
6516 errorMsg = mContext.getResources().getText(
6517 com.android.internal.R.string.factorytest_not_system);
6518 }
6519 } else {
6520 errorMsg = mContext.getResources().getText(
6521 com.android.internal.R.string.factorytest_no_action);
6522 }
6523 if (errorMsg != null) {
6524 mTopAction = null;
6525 mTopData = null;
6526 mTopComponent = null;
6527 Message msg = Message.obtain();
6528 msg.what = SHOW_FACTORY_ERROR_MSG;
6529 msg.getData().putCharSequence("msg", errorMsg);
6530 mHandler.sendMessage(msg);
6531 }
6532 }
6533 }
6534
6535 retrieveSettings();
6536
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006537 if (goingCallback != null) goingCallback.run();
6538
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006539 synchronized (this) {
6540 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
6541 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006542 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07006543 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006544 if (apps != null) {
6545 int N = apps.size();
6546 int i;
6547 for (i=0; i<N; i++) {
6548 ApplicationInfo info
6549 = (ApplicationInfo)apps.get(i);
6550 if (info != null &&
6551 !info.packageName.equals("android")) {
6552 addAppLocked(info);
6553 }
6554 }
6555 }
6556 } catch (RemoteException ex) {
6557 // pm is in same process, this will never happen.
6558 }
6559 }
6560
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006561 // Start up initial activity.
6562 mBooting = true;
6563
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006564 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006565 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006566 Message msg = Message.obtain();
6567 msg.what = SHOW_UID_ERROR_MSG;
6568 mHandler.sendMessage(msg);
6569 }
6570 } catch (RemoteException e) {
6571 }
6572
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006573 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006574 }
6575 }
6576
Dan Egnorb7f03672009-12-09 16:22:32 -08006577 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006578 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006579 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006580 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006581 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006582 startAppProblemLocked(app);
6583 app.stopFreezingAllLocked();
6584 return handleAppCrashLocked(app);
6585 }
6586
Dan Egnorb7f03672009-12-09 16:22:32 -08006587 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006588 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006589 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006590 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006591 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
6592 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006593 startAppProblemLocked(app);
6594 app.stopFreezingAllLocked();
6595 }
6596
6597 /**
6598 * Generate a process error record, suitable for attachment to a ProcessRecord.
6599 *
6600 * @param app The ProcessRecord in which the error occurred.
6601 * @param condition Crashing, Application Not Responding, etc. Values are defined in
6602 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08006603 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006604 * @param shortMsg Short message describing the crash.
6605 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08006606 * @param stackTrace Full crash stack trace, may be null.
6607 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006608 * @return Returns a fully-formed AppErrorStateInfo record.
6609 */
6610 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006611 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006612 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08006613
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006614 report.condition = condition;
6615 report.processName = app.processName;
6616 report.pid = app.pid;
6617 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08006618 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006619 report.shortMsg = shortMsg;
6620 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08006621 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006622
6623 return report;
6624 }
6625
Dan Egnor42471dd2010-01-07 17:25:22 -08006626 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006627 synchronized (this) {
6628 app.crashing = false;
6629 app.crashingReport = null;
6630 app.notResponding = false;
6631 app.notRespondingReport = null;
6632 if (app.anrDialog == fromDialog) {
6633 app.anrDialog = null;
6634 }
6635 if (app.waitDialog == fromDialog) {
6636 app.waitDialog = null;
6637 }
6638 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08006639 handleAppCrashLocked(app);
Dianne Hackborn8633e682010-04-22 16:03:41 -07006640 Slog.i(ActivityManagerService.TAG, "Killing "
6641 + app.processName + " (pid=" + app.pid + "): user's request");
6642 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
6643 app.processName, app.setAdj, "user's request after error");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006644 Process.killProcess(app.pid);
6645 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006646 }
6647 }
Dan Egnor42471dd2010-01-07 17:25:22 -08006648
Dan Egnorb7f03672009-12-09 16:22:32 -08006649 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006650 long now = SystemClock.uptimeMillis();
6651
6652 Long crashTime = mProcessCrashTimes.get(app.info.processName,
6653 app.info.uid);
6654 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
6655 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006656 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006657 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006658 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006659 app.info.processName, app.info.uid);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006660 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
6661 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006662 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006663 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006664 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006665 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006666 }
6667 }
6668 if (!app.persistent) {
Dianne Hackborn070783f2010-12-29 16:46:28 -08006669 // Don't let services in this process be restarted and potentially
6670 // annoy the user repeatedly. Unless it is persistent, since those
6671 // processes run critical code.
6672 killServicesLocked(app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006673 // We don't want to start this process again until the user
6674 // explicitly does so... but for persistent process, we really
6675 // need to keep it running. If a persistent process is actually
6676 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08006677 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006678 app.info.processName);
6679 mBadProcesses.put(app.info.processName, app.info.uid, now);
6680 app.bad = true;
6681 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
6682 app.removed = true;
6683 removeProcessLocked(app, false);
Dianne Hackborncb44d962011-03-10 17:02:27 -08006684 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006685 return false;
6686 }
Dianne Hackborncb44d962011-03-10 17:02:27 -08006687 mMainStack.resumeTopActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006688 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006689 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006690 if (r.app == app) {
6691 // If the top running activity is from this crashing
6692 // process, then terminate it to avoid getting in a loop.
6693 Slog.w(TAG, " Force finishing activity "
6694 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006695 int index = mMainStack.indexOfTokenLocked(r);
6696 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006697 Activity.RESULT_CANCELED, null, "crashed");
Dianne Hackborn070783f2010-12-29 16:46:28 -08006698 // Also terminate any activities below it that aren't yet
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006699 // stopped, to avoid a situation where one will get
6700 // re-start our crashing activity once it gets resumed again.
6701 index--;
6702 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006703 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006704 if (r.state == ActivityState.RESUMED
6705 || r.state == ActivityState.PAUSING
6706 || r.state == ActivityState.PAUSED) {
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -08006707 if (!r.isHomeActivity || mHomeProcess != r.app) {
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006708 Slog.w(TAG, " Force finishing activity "
6709 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006710 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006711 Activity.RESULT_CANCELED, null, "crashed");
6712 }
6713 }
6714 }
6715 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006716 }
6717
6718 // Bump up the crash count of any services currently running in the proc.
6719 if (app.services.size() != 0) {
6720 // Any services running in the application need to be placed
6721 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07006722 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006723 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006724 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006725 sr.crashCount++;
6726 }
6727 }
Mattias Larssona4fd0072010-06-22 22:37:03 +02006728
6729 // If the crashing process is what we consider to be the "home process" and it has been
6730 // replaced by a third-party app, clear the package preferred activities from packages
6731 // with a home activity running in the process to prevent a repeatedly crashing app
6732 // from blocking the user to manually clear the list.
6733 if (app == mHomeProcess && mHomeProcess.activities.size() > 0
6734 && (mHomeProcess.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
6735 Iterator it = mHomeProcess.activities.iterator();
6736 while (it.hasNext()) {
Jean-Baptiste Queru5ea89f72010-07-30 09:30:31 -07006737 ActivityRecord r = (ActivityRecord)it.next();
Mattias Larssona4fd0072010-06-22 22:37:03 +02006738 if (r.isHomeActivity) {
6739 Log.i(TAG, "Clearing package preferred activities from " + r.packageName);
6740 try {
6741 ActivityThread.getPackageManager()
6742 .clearPackagePreferredActivities(r.packageName);
6743 } catch (RemoteException c) {
6744 // pm is in same process, this will never happen.
6745 }
6746 }
6747 }
6748 }
6749
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006750 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
6751 return true;
6752 }
6753
6754 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006755 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
6756 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006757 skipCurrentReceiverLocked(app);
6758 }
6759
6760 void skipCurrentReceiverLocked(ProcessRecord app) {
6761 boolean reschedule = false;
6762 BroadcastRecord r = app.curReceiver;
6763 if (r != null) {
6764 // The current broadcast is waiting for this app's receiver
6765 // to be finished. Looks like that's not going to happen, so
6766 // let the broadcast continue.
Jeff Brown4d94a762010-09-23 11:33:28 -07006767 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006768 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6769 r.resultExtras, r.resultAbort, true);
6770 reschedule = true;
6771 }
6772 r = mPendingBroadcast;
6773 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006774 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006775 "skip & discard pending app " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -07006776 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006777 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6778 r.resultExtras, r.resultAbort, true);
6779 reschedule = true;
6780 }
6781 if (reschedule) {
6782 scheduleBroadcastsLocked();
6783 }
6784 }
6785
Dan Egnor60d87622009-12-16 16:32:58 -08006786 /**
6787 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
6788 * The application process will exit immediately after this call returns.
6789 * @param app object of the crashing app, null for the system server
6790 * @param crashInfo describing the exception
6791 */
6792 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
Dianne Hackborncb44d962011-03-10 17:02:27 -08006793 ProcessRecord r = findAppProcess(app, "Crash");
Dan Egnor60d87622009-12-16 16:32:58 -08006794
6795 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
6796 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006797 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006798 crashInfo.exceptionClassName,
6799 crashInfo.exceptionMessage,
6800 crashInfo.throwFileName,
6801 crashInfo.throwLineNumber);
6802
Dan Egnor42471dd2010-01-07 17:25:22 -08006803 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006804
6805 crashApplication(r, crashInfo);
6806 }
6807
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006808 public void handleApplicationStrictModeViolation(
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006809 IBinder app,
6810 int violationMask,
6811 StrictMode.ViolationInfo info) {
Dianne Hackborncb44d962011-03-10 17:02:27 -08006812 ProcessRecord r = findAppProcess(app, "StrictMode");
6813 if (r == null) {
6814 return;
6815 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006816
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006817 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -08006818 Integer stackFingerprint = info.hashCode();
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006819 boolean logIt = true;
6820 synchronized (mAlreadyLoggedViolatedStacks) {
6821 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
6822 logIt = false;
6823 // TODO: sub-sample into EventLog for these, with
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006824 // the info.durationMillis? Then we'd get
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006825 // the relative pain numbers, without logging all
6826 // the stack traces repeatedly. We'd want to do
6827 // likewise in the client code, which also does
6828 // dup suppression, before the Binder call.
6829 } else {
6830 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
6831 mAlreadyLoggedViolatedStacks.clear();
6832 }
6833 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
6834 }
6835 }
6836 if (logIt) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006837 logStrictModeViolationToDropBox(r, info);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006838 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006839 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006840
6841 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
6842 AppErrorResult result = new AppErrorResult();
6843 synchronized (this) {
6844 final long origId = Binder.clearCallingIdentity();
6845
6846 Message msg = Message.obtain();
6847 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
6848 HashMap<String, Object> data = new HashMap<String, Object>();
6849 data.put("result", result);
6850 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006851 data.put("violationMask", violationMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006852 data.put("info", info);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006853 msg.obj = data;
6854 mHandler.sendMessage(msg);
6855
6856 Binder.restoreCallingIdentity(origId);
6857 }
6858 int res = result.get();
Dianne Hackbornb424b632010-08-18 15:59:05 -07006859 Slog.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006860 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006861 }
6862
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006863 // Depending on the policy in effect, there could be a bunch of
6864 // these in quick succession so we try to batch these together to
6865 // minimize disk writes, number of dropbox entries, and maximize
6866 // compression, by having more fewer, larger records.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006867 private void logStrictModeViolationToDropBox(
6868 ProcessRecord process,
6869 StrictMode.ViolationInfo info) {
6870 if (info == null) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006871 return;
6872 }
6873 final boolean isSystemApp = process == null ||
6874 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
6875 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
6876 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
6877 final DropBoxManager dbox = (DropBoxManager)
6878 mContext.getSystemService(Context.DROPBOX_SERVICE);
6879
6880 // Exit early if the dropbox isn't configured to accept this report type.
6881 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
6882
6883 boolean bufferWasEmpty;
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006884 boolean needsFlush;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006885 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
6886 synchronized (sb) {
6887 bufferWasEmpty = sb.length() == 0;
6888 appendDropBoxProcessHeaders(process, sb);
6889 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
6890 sb.append("System-App: ").append(isSystemApp).append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006891 sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
6892 if (info.violationNumThisLoop != 0) {
6893 sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
6894 }
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07006895 if (info.numAnimationsRunning != 0) {
6896 sb.append("Animations-Running: ").append(info.numAnimationsRunning).append("\n");
6897 }
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07006898 if (info.broadcastIntentAction != null) {
6899 sb.append("Broadcast-Intent-Action: ").append(info.broadcastIntentAction).append("\n");
6900 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08006901 if (info.durationMillis != -1) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006902 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006903 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08006904 if (info.numInstances != -1) {
6905 sb.append("Instance-Count: ").append(info.numInstances).append("\n");
6906 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08006907 if (info.tags != null) {
6908 for (String tag : info.tags) {
6909 sb.append("Span-Tag: ").append(tag).append("\n");
6910 }
6911 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006912 sb.append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006913 if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
6914 sb.append(info.crashInfo.stackTrace);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006915 }
6916 sb.append("\n");
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006917
6918 // Only buffer up to ~64k. Various logging bits truncate
6919 // things at 128k.
6920 needsFlush = (sb.length() > 64 * 1024);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006921 }
6922
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006923 // Flush immediately if the buffer's grown too large, or this
6924 // is a non-system app. Non-system apps are isolated with a
6925 // different tag & policy and not batched.
6926 //
6927 // Batching is useful during internal testing with
6928 // StrictMode settings turned up high. Without batching,
6929 // thousands of separate files could be created on boot.
6930 if (!isSystemApp || needsFlush) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006931 new Thread("Error dump: " + dropboxTag) {
6932 @Override
6933 public void run() {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006934 String report;
6935 synchronized (sb) {
6936 report = sb.toString();
6937 sb.delete(0, sb.length());
6938 sb.trimToSize();
6939 }
6940 if (report.length() != 0) {
6941 dbox.addText(dropboxTag, report);
6942 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006943 }
6944 }.start();
6945 return;
6946 }
6947
6948 // System app batching:
6949 if (!bufferWasEmpty) {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07006950 // An existing dropbox-writing thread is outstanding, so
6951 // we don't need to start it up. The existing thread will
6952 // catch the buffer appends we just did.
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07006953 return;
6954 }
6955
6956 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
6957 // (After this point, we shouldn't access AMS internal data structures.)
6958 new Thread("Error dump: " + dropboxTag) {
6959 @Override
6960 public void run() {
6961 // 5 second sleep to let stacks arrive and be batched together
6962 try {
6963 Thread.sleep(5000); // 5 seconds
6964 } catch (InterruptedException e) {}
6965
6966 String errorReport;
6967 synchronized (mStrictModeBuffer) {
6968 errorReport = mStrictModeBuffer.toString();
6969 if (errorReport.length() == 0) {
6970 return;
6971 }
6972 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
6973 mStrictModeBuffer.trimToSize();
6974 }
6975 dbox.addText(dropboxTag, errorReport);
6976 }
6977 }.start();
6978 }
6979
Dan Egnor60d87622009-12-16 16:32:58 -08006980 /**
6981 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
6982 * @param app object of the crashing app, null for the system server
6983 * @param tag reported by the caller
6984 * @param crashInfo describing the context of the error
6985 * @return true if the process should exit immediately (WTF is fatal)
6986 */
6987 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08006988 ApplicationErrorReport.CrashInfo crashInfo) {
Dianne Hackborncb44d962011-03-10 17:02:27 -08006989 ProcessRecord r = findAppProcess(app, "WTF");
Dan Egnor60d87622009-12-16 16:32:58 -08006990
6991 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
6992 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006993 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006994 tag, crashInfo.exceptionMessage);
6995
Dan Egnor42471dd2010-01-07 17:25:22 -08006996 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006997
Doug Zongker43866e02010-01-07 12:09:54 -08006998 if (Settings.Secure.getInt(mContext.getContentResolver(),
6999 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08007000 crashApplication(r, crashInfo);
7001 return true;
7002 } else {
7003 return false;
7004 }
7005 }
7006
7007 /**
7008 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
7009 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
7010 */
Dianne Hackborncb44d962011-03-10 17:02:27 -08007011 private ProcessRecord findAppProcess(IBinder app, String reason) {
Dan Egnor60d87622009-12-16 16:32:58 -08007012 if (app == null) {
7013 return null;
7014 }
7015
7016 synchronized (this) {
7017 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
7018 final int NA = apps.size();
7019 for (int ia=0; ia<NA; ia++) {
7020 ProcessRecord p = apps.valueAt(ia);
7021 if (p.thread != null && p.thread.asBinder() == app) {
7022 return p;
7023 }
7024 }
7025 }
7026
Dianne Hackborncb44d962011-03-10 17:02:27 -08007027 Slog.w(TAG, "Can't find mystery application for " + reason
7028 + " from pid=" + Binder.getCallingPid()
7029 + " uid=" + Binder.getCallingUid() + ": " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08007030 return null;
7031 }
7032 }
7033
7034 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007035 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
7036 * to append various headers to the dropbox log text.
Dan Egnor60d87622009-12-16 16:32:58 -08007037 */
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07007038 private void appendDropBoxProcessHeaders(ProcessRecord process, StringBuilder sb) {
7039 // Note: ProcessRecord 'process' is guarded by the service
7040 // instance. (notably process.pkgList, which could otherwise change
7041 // concurrently during execution of this method)
7042 synchronized (this) {
7043 if (process == null || process.pid == MY_PID) {
7044 sb.append("Process: system_server\n");
7045 } else {
7046 sb.append("Process: ").append(process.processName).append("\n");
7047 }
7048 if (process == null) {
7049 return;
7050 }
Dan Egnora455d192010-03-12 08:52:28 -08007051 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007052 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08007053 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
7054 for (String pkg : process.pkgList) {
7055 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08007056 try {
Dan Egnora455d192010-03-12 08:52:28 -08007057 PackageInfo pi = pm.getPackageInfo(pkg, 0);
7058 if (pi != null) {
7059 sb.append(" v").append(pi.versionCode);
7060 if (pi.versionName != null) {
7061 sb.append(" (").append(pi.versionName).append(")");
7062 }
7063 }
7064 } catch (RemoteException e) {
7065 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08007066 }
Dan Egnora455d192010-03-12 08:52:28 -08007067 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08007068 }
Dan Egnora455d192010-03-12 08:52:28 -08007069 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007070 }
7071
7072 private static String processClass(ProcessRecord process) {
7073 if (process == null || process.pid == MY_PID) {
7074 return "system_server";
7075 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
7076 return "system_app";
7077 } else {
7078 return "data_app";
7079 }
7080 }
7081
7082 /**
7083 * Write a description of an error (crash, WTF, ANR) to the drop box.
7084 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
7085 * @param process which caused the error, null means the system server
7086 * @param activity which triggered the error, null if unknown
7087 * @param parent activity related to the error, null if unknown
7088 * @param subject line related to the error, null if absent
7089 * @param report in long form describing the error, null if absent
7090 * @param logFile to include in the report, null if none
7091 * @param crashInfo giving an application stack trace, null if absent
7092 */
7093 public void addErrorToDropBox(String eventType,
7094 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
7095 final String report, final File logFile,
7096 final ApplicationErrorReport.CrashInfo crashInfo) {
7097 // NOTE -- this must never acquire the ActivityManagerService lock,
7098 // otherwise the watchdog may be prevented from resetting the system.
7099
7100 final String dropboxTag = processClass(process) + "_" + eventType;
7101 final DropBoxManager dbox = (DropBoxManager)
7102 mContext.getSystemService(Context.DROPBOX_SERVICE);
7103
7104 // Exit early if the dropbox isn't configured to accept this report type.
7105 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
7106
7107 final StringBuilder sb = new StringBuilder(1024);
7108 appendDropBoxProcessHeaders(process, sb);
Dan Egnora455d192010-03-12 08:52:28 -08007109 if (activity != null) {
7110 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
7111 }
7112 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
7113 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
7114 }
7115 if (parent != null && parent != activity) {
7116 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
7117 }
7118 if (subject != null) {
7119 sb.append("Subject: ").append(subject).append("\n");
7120 }
7121 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
Christian Lindeberg03d2ca62010-09-28 14:52:20 +02007122 if (Debug.isDebuggerConnected()) {
7123 sb.append("Debugger: Connected\n");
7124 }
Dan Egnora455d192010-03-12 08:52:28 -08007125 sb.append("\n");
7126
7127 // Do the rest in a worker thread to avoid blocking the caller on I/O
7128 // (After this point, we shouldn't access AMS internal data structures.)
7129 Thread worker = new Thread("Error dump: " + dropboxTag) {
7130 @Override
7131 public void run() {
7132 if (report != null) {
7133 sb.append(report);
7134 }
7135 if (logFile != null) {
7136 try {
7137 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
7138 } catch (IOException e) {
7139 Slog.e(TAG, "Error reading " + logFile, e);
7140 }
7141 }
7142 if (crashInfo != null && crashInfo.stackTrace != null) {
7143 sb.append(crashInfo.stackTrace);
7144 }
7145
7146 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
7147 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
7148 if (lines > 0) {
7149 sb.append("\n");
7150
7151 // Merge several logcat streams, and take the last N lines
7152 InputStreamReader input = null;
7153 try {
7154 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
7155 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
7156 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
7157
7158 try { logcat.getOutputStream().close(); } catch (IOException e) {}
7159 try { logcat.getErrorStream().close(); } catch (IOException e) {}
7160 input = new InputStreamReader(logcat.getInputStream());
7161
7162 int num;
7163 char[] buf = new char[8192];
7164 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
7165 } catch (IOException e) {
7166 Slog.e(TAG, "Error running logcat", e);
7167 } finally {
7168 if (input != null) try { input.close(); } catch (IOException e) {}
7169 }
7170 }
7171
7172 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08007173 }
Dan Egnora455d192010-03-12 08:52:28 -08007174 };
7175
7176 if (process == null || process.pid == MY_PID) {
7177 worker.run(); // We may be about to die -- need to run this synchronously
7178 } else {
7179 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08007180 }
7181 }
7182
7183 /**
7184 * Bring up the "unexpected error" dialog box for a crashing app.
7185 * Deal with edge cases (intercepts from instrumented applications,
7186 * ActivityController, error intent receivers, that sort of thing).
7187 * @param r the application crashing
7188 * @param crashInfo describing the failure
7189 */
7190 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007191 long timeMillis = System.currentTimeMillis();
7192 String shortMsg = crashInfo.exceptionClassName;
7193 String longMsg = crashInfo.exceptionMessage;
7194 String stackTrace = crashInfo.stackTrace;
7195 if (shortMsg != null && longMsg != null) {
7196 longMsg = shortMsg + ": " + longMsg;
7197 } else if (shortMsg != null) {
7198 longMsg = shortMsg;
7199 }
7200
Dan Egnor60d87622009-12-16 16:32:58 -08007201 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007202 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007203 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007204 try {
7205 String name = r != null ? r.processName : null;
7206 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08007207 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08007208 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007209 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007210 + " at watcher's request");
7211 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08007212 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007213 }
7214 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007215 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007216 }
7217 }
7218
7219 final long origId = Binder.clearCallingIdentity();
7220
7221 // If this process is running instrumentation, finish it.
7222 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007223 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007224 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08007225 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
7226 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007227 Bundle info = new Bundle();
7228 info.putString("shortMsg", shortMsg);
7229 info.putString("longMsg", longMsg);
7230 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
7231 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007232 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007233 }
7234
Dan Egnor60d87622009-12-16 16:32:58 -08007235 // If we can't identify the process or it's already exceeded its crash quota,
7236 // quit right away without showing a crash dialog.
7237 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007238 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007239 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007240 }
7241
7242 Message msg = Message.obtain();
7243 msg.what = SHOW_ERROR_MSG;
7244 HashMap data = new HashMap();
7245 data.put("result", result);
7246 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007247 msg.obj = data;
7248 mHandler.sendMessage(msg);
7249
7250 Binder.restoreCallingIdentity(origId);
7251 }
7252
7253 int res = result.get();
7254
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007255 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007256 synchronized (this) {
7257 if (r != null) {
7258 mProcessCrashTimes.put(r.info.processName, r.info.uid,
7259 SystemClock.uptimeMillis());
7260 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007261 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007262 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007263 }
7264 }
7265
7266 if (appErrorIntent != null) {
7267 try {
7268 mContext.startActivity(appErrorIntent);
7269 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007270 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007271 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007272 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007273 }
Dan Egnorb7f03672009-12-09 16:22:32 -08007274
7275 Intent createAppErrorIntentLocked(ProcessRecord r,
7276 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
7277 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007278 if (report == null) {
7279 return null;
7280 }
7281 Intent result = new Intent(Intent.ACTION_APP_ERROR);
7282 result.setComponent(r.errorReportReceiver);
7283 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
7284 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
7285 return result;
7286 }
7287
Dan Egnorb7f03672009-12-09 16:22:32 -08007288 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
7289 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007290 if (r.errorReportReceiver == null) {
7291 return null;
7292 }
7293
7294 if (!r.crashing && !r.notResponding) {
7295 return null;
7296 }
7297
Dan Egnorb7f03672009-12-09 16:22:32 -08007298 ApplicationErrorReport report = new ApplicationErrorReport();
7299 report.packageName = r.info.packageName;
7300 report.installerPackageName = r.errorReportReceiver.getPackageName();
7301 report.processName = r.processName;
7302 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01007303 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007304
Dan Egnorb7f03672009-12-09 16:22:32 -08007305 if (r.crashing) {
7306 report.type = ApplicationErrorReport.TYPE_CRASH;
7307 report.crashInfo = crashInfo;
7308 } else if (r.notResponding) {
7309 report.type = ApplicationErrorReport.TYPE_ANR;
7310 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007311
Dan Egnorb7f03672009-12-09 16:22:32 -08007312 report.anrInfo.activity = r.notRespondingReport.tag;
7313 report.anrInfo.cause = r.notRespondingReport.shortMsg;
7314 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007315 }
7316
Dan Egnorb7f03672009-12-09 16:22:32 -08007317 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007318 }
7319
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007320 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
7321 // assume our apps are happy - lazy create the list
7322 List<ActivityManager.ProcessErrorStateInfo> errList = null;
7323
7324 synchronized (this) {
7325
7326 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007327 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7328 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007329 if ((app.thread != null) && (app.crashing || app.notResponding)) {
7330 // This one's in trouble, so we'll generate a report for it
7331 // crashes are higher priority (in case there's a crash *and* an anr)
7332 ActivityManager.ProcessErrorStateInfo report = null;
7333 if (app.crashing) {
7334 report = app.crashingReport;
7335 } else if (app.notResponding) {
7336 report = app.notRespondingReport;
7337 }
7338
7339 if (report != null) {
7340 if (errList == null) {
7341 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
7342 }
7343 errList.add(report);
7344 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007345 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007346 " crashing = " + app.crashing +
7347 " notResponding = " + app.notResponding);
7348 }
7349 }
7350 }
7351 }
7352
7353 return errList;
7354 }
7355
7356 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
7357 // Lazy instantiation of list
7358 List<ActivityManager.RunningAppProcessInfo> runList = null;
7359 synchronized (this) {
7360 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007361 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7362 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007363 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
7364 // Generate process state info for running application
7365 ActivityManager.RunningAppProcessInfo currApp =
7366 new ActivityManager.RunningAppProcessInfo(app.processName,
7367 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07007368 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007369 if (mHeavyWeightProcess == app) {
Dianne Hackborn482566e2010-09-03 12:51:28 -07007370 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007371 }
Dianne Hackborn42499172010-10-15 18:45:07 -07007372 if (app.persistent) {
7373 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_PERSISTENT;
7374 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007375 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007376 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007377 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
7378 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
7379 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08007380 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
7381 } else if (adj >= HOME_APP_ADJ) {
7382 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
7383 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007384 } else if (adj >= SECONDARY_SERVER_ADJ) {
7385 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007386 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackborn5383f502010-10-22 12:59:20 -07007387 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007388 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
7389 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007390 } else if (adj >= VISIBLE_APP_ADJ) {
7391 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
7392 } else {
7393 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
7394 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007395 currApp.importanceReasonCode = app.adjTypeCode;
7396 if (app.adjSource instanceof ProcessRecord) {
7397 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007398 } else if (app.adjSource instanceof ActivityRecord) {
7399 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007400 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
7401 }
7402 if (app.adjTarget instanceof ComponentName) {
7403 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
7404 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007405 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007406 // + " lru=" + currApp.lru);
7407 if (runList == null) {
7408 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
7409 }
7410 runList.add(currApp);
7411 }
7412 }
7413 }
7414 return runList;
7415 }
7416
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007417 public List<ApplicationInfo> getRunningExternalApplications() {
7418 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
7419 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
7420 if (runningApps != null && runningApps.size() > 0) {
7421 Set<String> extList = new HashSet<String>();
7422 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
7423 if (app.pkgList != null) {
7424 for (String pkg : app.pkgList) {
7425 extList.add(pkg);
7426 }
7427 }
7428 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007429 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007430 for (String pkg : extList) {
7431 try {
7432 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
7433 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
7434 retList.add(info);
7435 }
7436 } catch (RemoteException e) {
7437 }
7438 }
7439 }
7440 return retList;
7441 }
7442
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007443 @Override
7444 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007445 if (checkCallingPermission(android.Manifest.permission.DUMP)
7446 != PackageManager.PERMISSION_GRANTED) {
7447 pw.println("Permission Denial: can't dump ActivityManager from from pid="
7448 + Binder.getCallingPid()
7449 + ", uid=" + Binder.getCallingUid()
7450 + " without permission "
7451 + android.Manifest.permission.DUMP);
7452 return;
7453 }
7454
7455 boolean dumpAll = false;
7456
7457 int opti = 0;
7458 while (opti < args.length) {
7459 String opt = args[opti];
7460 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
7461 break;
7462 }
7463 opti++;
7464 if ("-a".equals(opt)) {
7465 dumpAll = true;
7466 } else if ("-h".equals(opt)) {
7467 pw.println("Activity manager dump options:");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007468 pw.println(" [-a] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007469 pw.println(" cmd may be one of:");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007470 pw.println(" a[ctivities]: activity stack state");
7471 pw.println(" b[roadcasts]: broadcast state");
7472 pw.println(" i[ntents]: pending intent state");
7473 pw.println(" p[rocesses]: process state");
7474 pw.println(" o[om]: out of memory management");
7475 pw.println(" prov[iders]: content provider state");
7476 pw.println(" s[ervices]: service state");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007477 pw.println(" service [name]: service client-side state");
Dianne Hackborn30d71892010-12-11 10:37:55 -08007478 pw.println(" cmd may also be a component name (com.foo/.myApp),");
7479 pw.println(" a partial substring in a component name, or an");
7480 pw.println(" ActivityRecord hex object identifier.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007481 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007482 } else {
7483 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007484 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007485 }
7486
7487 // Is the caller requesting to dump a particular piece of data?
7488 if (opti < args.length) {
7489 String cmd = args[opti];
7490 opti++;
7491 if ("activities".equals(cmd) || "a".equals(cmd)) {
7492 synchronized (this) {
7493 dumpActivitiesLocked(fd, pw, args, opti, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007494 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007495 return;
7496 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
7497 synchronized (this) {
7498 dumpBroadcastsLocked(fd, pw, args, opti, true);
7499 }
7500 return;
7501 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
7502 synchronized (this) {
7503 dumpPendingIntentsLocked(fd, pw, args, opti, true);
7504 }
7505 return;
7506 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
7507 synchronized (this) {
7508 dumpProcessesLocked(fd, pw, args, opti, true);
7509 }
7510 return;
Dianne Hackborn287952c2010-09-22 22:34:31 -07007511 } else if ("oom".equals(cmd) || "o".equals(cmd)) {
7512 synchronized (this) {
7513 dumpOomLocked(fd, pw, args, opti, true);
7514 }
7515 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007516 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
7517 synchronized (this) {
7518 dumpProvidersLocked(fd, pw, args, opti, true);
7519 }
7520 return;
7521 } else if ("service".equals(cmd)) {
Joe Onoratoeb95b082010-10-21 14:54:19 -04007522 dumpService(fd, pw, args, opti);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007523 return;
7524 } else if ("services".equals(cmd) || "s".equals(cmd)) {
7525 synchronized (this) {
7526 dumpServicesLocked(fd, pw, args, opti, true);
7527 }
7528 return;
Dianne Hackborn625ac272010-09-17 18:29:22 -07007529 } else {
7530 // Dumping a single activity?
7531 if (dumpActivity(fd, pw, cmd, args, opti, dumpAll)) {
7532 return;
7533 }
Dianne Hackborn30d71892010-12-11 10:37:55 -08007534 pw.println("Bad activity command, or no activities match: " + cmd);
7535 pw.println("Use -h for help.");
7536 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007537 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007538 }
7539
7540 // No piece of data specified, dump everything.
7541 synchronized (this) {
7542 boolean needSep;
7543 if (dumpAll) {
7544 pw.println("Providers in Current Activity Manager State:");
7545 }
7546 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
7547 if (needSep) {
7548 pw.println(" ");
7549 }
7550 if (dumpAll) {
7551 pw.println("-------------------------------------------------------------------------------");
7552 pw.println("Broadcasts in Current Activity Manager State:");
7553 }
7554 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
7555 if (needSep) {
7556 pw.println(" ");
7557 }
7558 if (dumpAll) {
7559 pw.println("-------------------------------------------------------------------------------");
7560 pw.println("Services in Current Activity Manager State:");
7561 }
7562 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll);
7563 if (needSep) {
7564 pw.println(" ");
7565 }
7566 if (dumpAll) {
7567 pw.println("-------------------------------------------------------------------------------");
7568 pw.println("PendingIntents in Current Activity Manager State:");
7569 }
7570 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
7571 if (needSep) {
7572 pw.println(" ");
7573 }
7574 if (dumpAll) {
7575 pw.println("-------------------------------------------------------------------------------");
7576 pw.println("Activities in Current Activity Manager State:");
7577 }
7578 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, !dumpAll);
7579 if (needSep) {
7580 pw.println(" ");
7581 }
7582 if (dumpAll) {
7583 pw.println("-------------------------------------------------------------------------------");
7584 pw.println("Processes in Current Activity Manager State:");
7585 }
7586 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
7587 }
7588 }
7589
7590 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7591 int opti, boolean dumpAll, boolean needHeader) {
7592 if (needHeader) {
7593 pw.println(" Activity stack:");
7594 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007595 dumpHistoryList(pw, mMainStack.mHistory, " ", "Hist", true);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007596 pw.println(" ");
7597 pw.println(" Running activities (most recent first):");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007598 dumpHistoryList(pw, mMainStack.mLRUActivities, " ", "Run", false);
7599 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007600 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007601 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007602 dumpHistoryList(pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007603 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007604 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007605 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007606 pw.println(" Activities waiting to stop:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007607 dumpHistoryList(pw, mMainStack.mStoppingActivities, " ", "Stop", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007608 }
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08007609 if (mMainStack.mGoingToSleepActivities.size() > 0) {
7610 pw.println(" ");
7611 pw.println(" Activities waiting to sleep:");
7612 dumpHistoryList(pw, mMainStack.mGoingToSleepActivities, " ", "Sleep", false);
7613 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007614 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007615 pw.println(" ");
7616 pw.println(" Activities waiting to finish:");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007617 dumpHistoryList(pw, mMainStack.mFinishingActivities, " ", "Fin", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007618 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007619
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007620 pw.println(" ");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007621 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
7622 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007623 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007624 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08007625 pw.println(" mSleepTimeout: " + mMainStack.mSleepTimeout);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007626
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007627 if (dumpAll && mRecentTasks.size() > 0) {
7628 pw.println(" ");
7629 pw.println("Recent tasks in Current Activity Manager State:");
7630
7631 final int N = mRecentTasks.size();
7632 for (int i=0; i<N; i++) {
7633 TaskRecord tr = mRecentTasks.get(i);
7634 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
7635 pw.println(tr);
7636 mRecentTasks.get(i).dump(pw, " ");
7637 }
7638 }
7639
7640 pw.println(" ");
7641 pw.println(" mCurTask: " + mCurTask);
7642
7643 return true;
7644 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07007645
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007646 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7647 int opti, boolean dumpAll) {
7648 boolean needSep = false;
7649 int numPers = 0;
7650
7651 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007652 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
7653 final int NA = procs.size();
7654 for (int ia=0; ia<NA; ia++) {
7655 if (!needSep) {
7656 pw.println(" All known processes:");
7657 needSep = true;
7658 }
7659 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007660 pw.print(r.persistent ? " *PERS*" : " *APP*");
7661 pw.print(" UID "); pw.print(procs.keyAt(ia));
7662 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007663 r.dump(pw, " ");
7664 if (r.persistent) {
7665 numPers++;
7666 }
7667 }
7668 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007669 }
7670
7671 if (mLruProcesses.size() > 0) {
7672 if (needSep) pw.println(" ");
7673 needSep = true;
7674 pw.println(" Running processes (most recent first):");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007675 dumpProcessOomList(pw, this, mLruProcesses, " ",
7676 "Proc", "PERS", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007677 needSep = true;
7678 }
7679
7680 synchronized (mPidsSelfLocked) {
7681 if (mPidsSelfLocked.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007682 if (needSep) pw.println(" ");
7683 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007684 pw.println(" PID mappings:");
7685 for (int i=0; i<mPidsSelfLocked.size(); i++) {
7686 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
7687 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007688 }
7689 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007690 }
7691
7692 if (mForegroundProcesses.size() > 0) {
7693 if (needSep) pw.println(" ");
7694 needSep = true;
7695 pw.println(" Foreground Processes:");
7696 for (int i=0; i<mForegroundProcesses.size(); i++) {
7697 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
7698 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007699 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007700 }
7701
7702 if (mPersistentStartingProcesses.size() > 0) {
7703 if (needSep) pw.println(" ");
7704 needSep = true;
7705 pw.println(" Persisent processes that are starting:");
7706 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007707 "Starting Norm", "Restarting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007708 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007709
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007710 if (mStartingProcesses.size() > 0) {
7711 if (needSep) pw.println(" ");
7712 needSep = true;
7713 pw.println(" Processes that are starting:");
7714 dumpProcessList(pw, this, mStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007715 "Starting Norm", "Starting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007716 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007717
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007718 if (mRemovedProcesses.size() > 0) {
7719 if (needSep) pw.println(" ");
7720 needSep = true;
7721 pw.println(" Processes that are being removed:");
7722 dumpProcessList(pw, this, mRemovedProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007723 "Removed Norm", "Removed PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007724 }
7725
7726 if (mProcessesOnHold.size() > 0) {
7727 if (needSep) pw.println(" ");
7728 needSep = true;
7729 pw.println(" Processes that are on old until the system is ready:");
7730 dumpProcessList(pw, this, mProcessesOnHold, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007731 "OnHold Norm", "OnHold PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007732 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007733
Dianne Hackborn287952c2010-09-22 22:34:31 -07007734 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007735
7736 if (mProcessCrashTimes.getMap().size() > 0) {
7737 if (needSep) pw.println(" ");
7738 needSep = true;
7739 pw.println(" Time since processes crashed:");
7740 long now = SystemClock.uptimeMillis();
7741 for (Map.Entry<String, SparseArray<Long>> procs
7742 : mProcessCrashTimes.getMap().entrySet()) {
7743 SparseArray<Long> uids = procs.getValue();
7744 final int N = uids.size();
7745 for (int i=0; i<N; i++) {
7746 pw.print(" Process "); pw.print(procs.getKey());
7747 pw.print(" uid "); pw.print(uids.keyAt(i));
7748 pw.print(": last crashed ");
7749 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007750 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007751 }
7752 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007753 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007754
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007755 if (mBadProcesses.getMap().size() > 0) {
7756 if (needSep) pw.println(" ");
7757 needSep = true;
7758 pw.println(" Bad processes:");
7759 for (Map.Entry<String, SparseArray<Long>> procs
7760 : mBadProcesses.getMap().entrySet()) {
7761 SparseArray<Long> uids = procs.getValue();
7762 final int N = uids.size();
7763 for (int i=0; i<N; i++) {
7764 pw.print(" Bad process "); pw.print(procs.getKey());
7765 pw.print(" uid "); pw.print(uids.keyAt(i));
7766 pw.print(": crashed at time ");
7767 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007768 }
7769 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007770 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007771
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007772 pw.println(" ");
7773 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007774 if (mHeavyWeightProcess != null) {
7775 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7776 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007777 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007778 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007779 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
7780 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
7781 || mOrigWaitForDebugger) {
7782 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
7783 + " mDebugTransient=" + mDebugTransient
7784 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
7785 }
7786 if (mAlwaysFinishActivities || mController != null) {
7787 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
7788 + " mController=" + mController);
7789 }
7790 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007791 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007792 pw.println(" mStartRunning=" + mStartRunning
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07007793 + " mProcessesReady=" + mProcessesReady
7794 + " mSystemReady=" + mSystemReady);
7795 pw.println(" mBooting=" + mBooting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007796 + " mBooted=" + mBooted
7797 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn287952c2010-09-22 22:34:31 -07007798 pw.print(" mLastPowerCheckRealtime=");
7799 TimeUtils.formatDuration(mLastPowerCheckRealtime, pw);
7800 pw.println("");
7801 pw.print(" mLastPowerCheckUptime=");
7802 TimeUtils.formatDuration(mLastPowerCheckUptime, pw);
7803 pw.println("");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007804 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
7805 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07007806 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007807 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007808
7809 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007810 }
7811
Dianne Hackborn287952c2010-09-22 22:34:31 -07007812 boolean dumpProcessesToGc(FileDescriptor fd, PrintWriter pw, String[] args,
7813 int opti, boolean needSep, boolean dumpAll) {
7814 if (mProcessesToGc.size() > 0) {
7815 if (needSep) pw.println(" ");
7816 needSep = true;
7817 pw.println(" Processes that are waiting to GC:");
7818 long now = SystemClock.uptimeMillis();
7819 for (int i=0; i<mProcessesToGc.size(); i++) {
7820 ProcessRecord proc = mProcessesToGc.get(i);
7821 pw.print(" Process "); pw.println(proc);
7822 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
7823 pw.print(", last gced=");
7824 pw.print(now-proc.lastRequestedGc);
7825 pw.print(" ms ago, last lowMem=");
7826 pw.print(now-proc.lastLowMemory);
7827 pw.println(" ms ago");
7828
7829 }
7830 }
7831 return needSep;
7832 }
7833
7834 boolean dumpOomLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7835 int opti, boolean dumpAll) {
7836 boolean needSep = false;
7837
7838 if (mLruProcesses.size() > 0) {
7839 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>(mLruProcesses);
7840
7841 Comparator<ProcessRecord> comparator = new Comparator<ProcessRecord>() {
7842 @Override
7843 public int compare(ProcessRecord object1, ProcessRecord object2) {
7844 if (object1.setAdj != object2.setAdj) {
7845 return object1.setAdj > object2.setAdj ? -1 : 1;
7846 }
7847 if (object1.setSchedGroup != object2.setSchedGroup) {
7848 return object1.setSchedGroup > object2.setSchedGroup ? -1 : 1;
7849 }
7850 if (object1.keeping != object2.keeping) {
7851 return object1.keeping ? -1 : 1;
7852 }
7853 if (object1.pid != object2.pid) {
7854 return object1.pid > object2.pid ? -1 : 1;
7855 }
7856 return 0;
7857 }
7858 };
7859
7860 Collections.sort(procs, comparator);
7861
7862 if (needSep) pw.println(" ");
7863 needSep = true;
7864 pw.println(" Process OOM control:");
7865 dumpProcessOomList(pw, this, procs, " ",
7866 "Proc", "PERS", true);
7867 needSep = true;
7868 }
7869
7870 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
7871
7872 pw.println(" ");
7873 pw.println(" mHomeProcess: " + mHomeProcess);
7874 if (mHeavyWeightProcess != null) {
7875 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7876 }
7877
7878 return true;
7879 }
7880
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007881 /**
7882 * There are three ways to call this:
7883 * - no service specified: dump all the services
7884 * - a flattened component name that matched an existing service was specified as the
7885 * first arg: dump that one service
7886 * - the first arg isn't the flattened component name of an existing service:
7887 * dump all services whose component contains the first arg as a substring
7888 */
Joe Onoratoeb95b082010-10-21 14:54:19 -04007889 protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args, int opti) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007890 String[] newArgs;
7891 String componentNameString;
7892 ServiceRecord r;
Kenny Root3619b9ab2010-02-13 10:05:42 -08007893 if (opti >= args.length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007894 componentNameString = null;
7895 newArgs = EMPTY_STRING_ARRAY;
7896 r = null;
7897 } else {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007898 componentNameString = args[opti];
7899 opti++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007900 ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007901 synchronized (this) {
7902 r = componentName != null ? mServices.get(componentName) : null;
7903 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007904 newArgs = new String[args.length - opti];
7905 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007906 }
7907
7908 if (r != null) {
Joe Onoratoeb95b082010-10-21 14:54:19 -04007909 dumpService(fd, pw, r, newArgs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007910 } else {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007911 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
7912 synchronized (this) {
7913 for (ServiceRecord r1 : mServices.values()) {
7914 if (componentNameString == null
7915 || r1.name.flattenToString().contains(componentNameString)) {
7916 services.add(r1);
7917 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007918 }
7919 }
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007920 for (int i=0; i<services.size(); i++) {
Joe Onoratoeb95b082010-10-21 14:54:19 -04007921 dumpService(fd, pw, services.get(i), newArgs);
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007922 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007923 }
7924 }
7925
7926 /**
7927 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
7928 * there is a thread associated with the service.
7929 */
Joe Onoratoeb95b082010-10-21 14:54:19 -04007930 private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args) {
7931 pw.println("------------------------------------------------------------"
7932 + "-------------------");
7933 pw.println("APP SERVICE: " + r.name.flattenToString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007934 if (r.app != null && r.app.thread != null) {
7935 try {
7936 // flush anything that is already in the PrintWriter since the thread is going
7937 // to write to the file descriptor directly
7938 pw.flush();
7939 r.app.thread.dumpService(fd, r, args);
7940 pw.print("\n");
Dianne Hackborn14bfa392010-07-24 19:58:06 -07007941 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007942 } catch (RemoteException e) {
7943 pw.println("got a RemoteException while dumping the service");
7944 }
7945 }
7946 }
7947
Dianne Hackborn625ac272010-09-17 18:29:22 -07007948 /**
7949 * There are three things that cmd can be:
7950 * - a flattened component name that matched an existing activity
7951 * - the cmd arg isn't the flattened component name of an existing activity:
7952 * dump all activity whose component contains the cmd as a substring
7953 * - A hex number of the ActivityRecord object instance.
7954 */
7955 protected boolean dumpActivity(FileDescriptor fd, PrintWriter pw, String name, String[] args,
7956 int opti, boolean dumpAll) {
7957 String[] newArgs;
7958 ComponentName componentName = ComponentName.unflattenFromString(name);
7959 int objectId = 0;
Dianne Hackborn30d71892010-12-11 10:37:55 -08007960 if (componentName == null) {
7961 // Not a '/' separated full component name; maybe an object ID?
7962 try {
7963 objectId = Integer.parseInt(name, 16);
7964 name = null;
7965 componentName = null;
7966 } catch (RuntimeException e) {
7967 }
Dianne Hackborn625ac272010-09-17 18:29:22 -07007968 }
7969 newArgs = new String[args.length - opti];
7970 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
7971
7972 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
7973 synchronized (this) {
7974 for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
7975 if (componentName != null) {
7976 if (r1.intent.getComponent().equals(componentName)) {
7977 activities.add(r1);
7978 }
7979 } else if (name != null) {
7980 if (r1.intent.getComponent().flattenToString().contains(name)) {
7981 activities.add(r1);
7982 }
Dianne Hackborn30d71892010-12-11 10:37:55 -08007983 } else if (System.identityHashCode(r1) == objectId) {
Dianne Hackborn625ac272010-09-17 18:29:22 -07007984 activities.add(r1);
7985 }
7986 }
7987 }
7988
7989 if (activities.size() <= 0) {
7990 return false;
7991 }
7992
Dianne Hackborn30d71892010-12-11 10:37:55 -08007993 TaskRecord lastTask = null;
7994 for (int i=activities.size()-1; i>=0; i--) {
7995 ActivityRecord r = (ActivityRecord)activities.get(i);
7996 if (lastTask != r.task) {
7997 lastTask = r.task;
7998 pw.print("* Task "); pw.print(lastTask.affinity);
7999 pw.print(" id="); pw.println(lastTask.taskId);
8000 if (dumpAll) {
8001 lastTask.dump(pw, " ");
8002 }
8003 }
8004 dumpActivity(" ", fd, pw, activities.get(i), newArgs, dumpAll);
Dianne Hackborn625ac272010-09-17 18:29:22 -07008005 }
8006 return true;
8007 }
8008
8009 /**
8010 * Invokes IApplicationThread.dumpActivity() on the thread of the specified activity if
8011 * there is a thread associated with the activity.
8012 */
Dianne Hackborn30d71892010-12-11 10:37:55 -08008013 private void dumpActivity(String prefix, FileDescriptor fd, PrintWriter pw,
8014 ActivityRecord r, String[] args, boolean dumpAll) {
8015 synchronized (this) {
8016 pw.print(prefix); pw.print("* Activity ");
8017 pw.print(Integer.toHexString(System.identityHashCode(r)));
8018 pw.print(" "); pw.print(r.shortComponentName); pw.print(" pid=");
8019 if (r.app != null) pw.println(r.app.pid);
8020 else pw.println("(not running)");
8021 if (dumpAll) {
8022 r.dump(pw, prefix + " ");
Dianne Hackborn625ac272010-09-17 18:29:22 -07008023 }
Dianne Hackborn625ac272010-09-17 18:29:22 -07008024 }
8025 if (r.app != null && r.app.thread != null) {
8026 try {
8027 // flush anything that is already in the PrintWriter since the thread is going
8028 // to write to the file descriptor directly
8029 pw.flush();
Dianne Hackborn30d71892010-12-11 10:37:55 -08008030 r.app.thread.dumpActivity(fd, r, prefix + " ", args);
Dianne Hackborn625ac272010-09-17 18:29:22 -07008031 pw.flush();
8032 } catch (RemoteException e) {
8033 pw.println("got a RemoteException while dumping the activity");
8034 }
8035 }
8036 }
8037
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008038 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8039 int opti, boolean dumpAll) {
8040 boolean needSep = false;
8041
8042 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008043 if (mRegisteredReceivers.size() > 0) {
8044 pw.println(" ");
8045 pw.println(" Registered Receivers:");
8046 Iterator it = mRegisteredReceivers.values().iterator();
8047 while (it.hasNext()) {
8048 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008049 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008050 r.dump(pw, " ");
8051 }
8052 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008053
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008054 pw.println(" ");
8055 pw.println("Receiver Resolver Table:");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008056 mReceiverResolver.dump(pw, null, " ", null, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008057 needSep = true;
8058 }
8059
8060 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
8061 || mPendingBroadcast != null) {
8062 if (mParallelBroadcasts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008063 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008064 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008065 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008066 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
8067 pw.println(" Broadcast #" + i + ":");
8068 mParallelBroadcasts.get(i).dump(pw, " ");
8069 }
8070 if (mOrderedBroadcasts.size() > 0) {
8071 pw.println(" ");
Dianne Hackborn399cccb2010-04-13 22:57:49 -07008072 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008073 }
8074 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
8075 pw.println(" Serialized Broadcast #" + i + ":");
8076 mOrderedBroadcasts.get(i).dump(pw, " ");
8077 }
8078 pw.println(" ");
8079 pw.println(" Pending broadcast:");
8080 if (mPendingBroadcast != null) {
8081 mPendingBroadcast.dump(pw, " ");
8082 } else {
8083 pw.println(" (null)");
8084 }
8085 needSep = true;
8086 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008087
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008088 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008089 pw.println(" ");
Dianne Hackborn12527f92009-11-11 17:39:50 -08008090 pw.println(" Historical broadcasts:");
8091 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
8092 BroadcastRecord r = mBroadcastHistory[i];
8093 if (r == null) {
8094 break;
8095 }
8096 pw.println(" Historical Broadcast #" + i + ":");
8097 r.dump(pw, " ");
8098 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008099 needSep = true;
8100 }
8101
8102 if (mStickyBroadcasts != null) {
Dianne Hackborn12527f92009-11-11 17:39:50 -08008103 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008104 pw.println(" Sticky broadcasts:");
8105 StringBuilder sb = new StringBuilder(128);
8106 for (Map.Entry<String, ArrayList<Intent>> ent
8107 : mStickyBroadcasts.entrySet()) {
8108 pw.print(" * Sticky action "); pw.print(ent.getKey());
8109 pw.println(":");
8110 ArrayList<Intent> intents = ent.getValue();
8111 final int N = intents.size();
8112 for (int i=0; i<N; i++) {
8113 sb.setLength(0);
8114 sb.append(" Intent: ");
8115 intents.get(i).toShortString(sb, true, false);
8116 pw.println(sb.toString());
8117 Bundle bundle = intents.get(i).getExtras();
8118 if (bundle != null) {
8119 pw.print(" ");
8120 pw.println(bundle.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008121 }
8122 }
8123 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008124 needSep = true;
8125 }
8126
8127 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008128 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008129 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008130 pw.println(" mHandler:");
8131 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008132 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008133 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008134
8135 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008136 }
8137
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008138 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8139 int opti, boolean dumpAll) {
8140 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008141
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008142 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008143 if (mServices.size() > 0) {
8144 pw.println(" Active services:");
8145 Iterator<ServiceRecord> it = mServices.values().iterator();
8146 while (it.hasNext()) {
8147 ServiceRecord r = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008148 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008149 r.dump(pw, " ");
8150 }
8151 needSep = true;
8152 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008153 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008154
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008155 if (mPendingServices.size() > 0) {
8156 if (needSep) pw.println(" ");
8157 pw.println(" Pending services:");
8158 for (int i=0; i<mPendingServices.size(); i++) {
8159 ServiceRecord r = mPendingServices.get(i);
8160 pw.print(" * Pending "); pw.println(r);
8161 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008162 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008163 needSep = true;
8164 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008165
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008166 if (mRestartingServices.size() > 0) {
8167 if (needSep) pw.println(" ");
8168 pw.println(" Restarting services:");
8169 for (int i=0; i<mRestartingServices.size(); i++) {
8170 ServiceRecord r = mRestartingServices.get(i);
8171 pw.print(" * Restarting "); pw.println(r);
8172 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008173 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008174 needSep = true;
8175 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008176
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008177 if (mStoppingServices.size() > 0) {
8178 if (needSep) pw.println(" ");
8179 pw.println(" Stopping services:");
8180 for (int i=0; i<mStoppingServices.size(); i++) {
8181 ServiceRecord r = mStoppingServices.get(i);
8182 pw.print(" * Stopping "); pw.println(r);
8183 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008184 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008185 needSep = true;
8186 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008187
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008188 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008189 if (mServiceConnections.size() > 0) {
8190 if (needSep) pw.println(" ");
8191 pw.println(" Connection bindings to services:");
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008192 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008193 = mServiceConnections.values().iterator();
8194 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008195 ArrayList<ConnectionRecord> r = it.next();
8196 for (int i=0; i<r.size(); i++) {
8197 pw.print(" * "); pw.println(r.get(i));
8198 r.get(i).dump(pw, " ");
8199 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008200 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008201 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008202 }
8203 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008204
8205 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008206 }
8207
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008208 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8209 int opti, boolean dumpAll) {
8210 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008211
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008212 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008213 if (mProvidersByClass.size() > 0) {
8214 if (needSep) pw.println(" ");
8215 pw.println(" Published content providers (by class):");
Dianne Hackborn860755f2010-06-03 18:47:52 -07008216 Iterator<Map.Entry<String, ContentProviderRecord>> it
8217 = mProvidersByClass.entrySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008218 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008219 Map.Entry<String, ContentProviderRecord> e = it.next();
8220 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008221 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008222 r.dump(pw, " ");
8223 }
8224 needSep = true;
8225 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008226
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008227 if (mProvidersByName.size() > 0) {
8228 pw.println(" ");
8229 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -07008230 Iterator<Map.Entry<String, ContentProviderRecord>> it
8231 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008232 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008233 Map.Entry<String, ContentProviderRecord> e = it.next();
8234 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008235 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
8236 pw.println(r);
8237 }
8238 needSep = true;
8239 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008240 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008241
8242 if (mLaunchingProviders.size() > 0) {
8243 if (needSep) pw.println(" ");
8244 pw.println(" Launching content providers:");
8245 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
8246 pw.print(" Launching #"); pw.print(i); pw.print(": ");
8247 pw.println(mLaunchingProviders.get(i));
8248 }
8249 needSep = true;
8250 }
8251
8252 if (mGrantedUriPermissions.size() > 0) {
8253 pw.println();
8254 pw.println("Granted Uri Permissions:");
8255 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
8256 int uid = mGrantedUriPermissions.keyAt(i);
8257 HashMap<Uri, UriPermission> perms
8258 = mGrantedUriPermissions.valueAt(i);
8259 pw.print(" * UID "); pw.print(uid);
8260 pw.println(" holds:");
8261 for (UriPermission perm : perms.values()) {
8262 pw.print(" "); pw.println(perm);
8263 perm.dump(pw, " ");
8264 }
8265 }
8266 needSep = true;
8267 }
8268
8269 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008270 }
8271
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008272 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8273 int opti, boolean dumpAll) {
8274 boolean needSep = false;
8275
8276 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008277 if (this.mIntentSenderRecords.size() > 0) {
8278 Iterator<WeakReference<PendingIntentRecord>> it
8279 = mIntentSenderRecords.values().iterator();
8280 while (it.hasNext()) {
8281 WeakReference<PendingIntentRecord> ref = it.next();
8282 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008283 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008284 if (rec != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008285 pw.print(" * "); pw.println(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008286 rec.dump(pw, " ");
8287 } else {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008288 pw.print(" * "); pw.print(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008289 }
8290 }
8291 }
8292 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008293
8294 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008295 }
8296
8297 private static final void dumpHistoryList(PrintWriter pw, List list,
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008298 String prefix, String label, boolean complete) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008299 TaskRecord lastTask = null;
8300 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008301 ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008302 final boolean full = complete || !r.inHistory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008303 if (lastTask != r.task) {
8304 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008305 pw.print(prefix);
8306 pw.print(full ? "* " : " ");
8307 pw.println(lastTask);
8308 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008309 lastTask.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008310 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008311 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008312 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
8313 pw.print(" #"); pw.print(i); pw.print(": ");
8314 pw.println(r);
8315 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008316 r.dump(pw, prefix + " ");
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008317 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008318 }
8319 }
8320
Dianne Hackborn09c916b2009-12-08 14:50:51 -08008321 private static String buildOomTag(String prefix, String space, int val, int base) {
8322 if (val == base) {
8323 if (space == null) return prefix;
8324 return prefix + " ";
8325 }
8326 return prefix + "+" + Integer.toString(val-base);
8327 }
8328
8329 private static final int dumpProcessList(PrintWriter pw,
8330 ActivityManagerService service, List list,
Dianne Hackborn287952c2010-09-22 22:34:31 -07008331 String prefix, String normalLabel, String persistentLabel) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008332 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07008333 final int N = list.size()-1;
8334 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008335 ProcessRecord r = (ProcessRecord)list.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008336 pw.println(String.format("%s%s #%2d: %s",
8337 prefix, (r.persistent ? persistentLabel : normalLabel),
8338 i, r.toString()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008339 if (r.persistent) {
8340 numPers++;
8341 }
8342 }
8343 return numPers;
8344 }
8345
Dianne Hackborn287952c2010-09-22 22:34:31 -07008346 private static final void dumpProcessOomList(PrintWriter pw,
8347 ActivityManagerService service, List<ProcessRecord> list,
8348 String prefix, String normalLabel, String persistentLabel,
8349 boolean inclDetails) {
8350
8351 final long curRealtime = SystemClock.elapsedRealtime();
8352 final long realtimeSince = curRealtime - service.mLastPowerCheckRealtime;
8353 final long curUptime = SystemClock.uptimeMillis();
8354 final long uptimeSince = curUptime - service.mLastPowerCheckUptime;
8355
8356 final int N = list.size()-1;
8357 for (int i=N; i>=0; i--) {
8358 ProcessRecord r = list.get(i);
8359 String oomAdj;
8360 if (r.setAdj >= EMPTY_APP_ADJ) {
8361 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
8362 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
8363 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
8364 } else if (r.setAdj >= HOME_APP_ADJ) {
8365 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
8366 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
8367 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
8368 } else if (r.setAdj >= BACKUP_APP_ADJ) {
8369 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
8370 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
8371 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
8372 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
8373 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
8374 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
8375 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
8376 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
8377 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
8378 } else if (r.setAdj >= CORE_SERVER_ADJ) {
8379 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
8380 } else if (r.setAdj >= SYSTEM_ADJ) {
8381 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
8382 } else {
8383 oomAdj = Integer.toString(r.setAdj);
8384 }
8385 String schedGroup;
8386 switch (r.setSchedGroup) {
8387 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
8388 schedGroup = "B";
8389 break;
8390 case Process.THREAD_GROUP_DEFAULT:
8391 schedGroup = "F";
8392 break;
8393 default:
8394 schedGroup = Integer.toString(r.setSchedGroup);
8395 break;
8396 }
8397 pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
8398 prefix, (r.persistent ? persistentLabel : normalLabel),
8399 N-i, oomAdj, schedGroup, r.toShortString(), r.adjType));
8400 if (r.adjSource != null || r.adjTarget != null) {
8401 pw.print(prefix);
8402 pw.print(" ");
8403 if (r.adjTarget instanceof ComponentName) {
8404 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
8405 } else if (r.adjTarget != null) {
8406 pw.print(r.adjTarget.toString());
8407 } else {
8408 pw.print("{null}");
8409 }
8410 pw.print("<=");
8411 if (r.adjSource instanceof ProcessRecord) {
8412 pw.print("Proc{");
8413 pw.print(((ProcessRecord)r.adjSource).toShortString());
8414 pw.println("}");
8415 } else if (r.adjSource != null) {
8416 pw.println(r.adjSource.toString());
8417 } else {
8418 pw.println("{null}");
8419 }
8420 }
8421 if (inclDetails) {
8422 pw.print(prefix);
8423 pw.print(" ");
8424 pw.print("oom: max="); pw.print(r.maxAdj);
8425 pw.print(" hidden="); pw.print(r.hiddenAdj);
8426 pw.print(" curRaw="); pw.print(r.curRawAdj);
8427 pw.print(" setRaw="); pw.print(r.setRawAdj);
8428 pw.print(" cur="); pw.print(r.curAdj);
8429 pw.print(" set="); pw.println(r.setAdj);
8430 pw.print(prefix);
8431 pw.print(" ");
8432 pw.print("keeping="); pw.print(r.keeping);
8433 pw.print(" hidden="); pw.print(r.hidden);
8434 pw.print(" empty="); pw.println(r.empty);
8435
8436 if (!r.keeping) {
8437 if (r.lastWakeTime != 0) {
8438 long wtime;
8439 BatteryStatsImpl stats = service.mBatteryStatsService.getActiveStatistics();
8440 synchronized (stats) {
8441 wtime = stats.getProcessWakeTime(r.info.uid,
8442 r.pid, curRealtime);
8443 }
8444 long timeUsed = wtime - r.lastWakeTime;
8445 pw.print(prefix);
8446 pw.print(" ");
8447 pw.print("keep awake over ");
8448 TimeUtils.formatDuration(realtimeSince, pw);
8449 pw.print(" used ");
8450 TimeUtils.formatDuration(timeUsed, pw);
8451 pw.print(" (");
8452 pw.print((timeUsed*100)/realtimeSince);
8453 pw.println("%)");
8454 }
8455 if (r.lastCpuTime != 0) {
8456 long timeUsed = r.curCpuTime - r.lastCpuTime;
8457 pw.print(prefix);
8458 pw.print(" ");
8459 pw.print("run cpu over ");
8460 TimeUtils.formatDuration(uptimeSince, pw);
8461 pw.print(" used ");
8462 TimeUtils.formatDuration(timeUsed, pw);
8463 pw.print(" (");
8464 pw.print((timeUsed*100)/uptimeSince);
8465 pw.println("%)");
8466 }
8467 }
8468 }
8469 }
8470 }
8471
Dianne Hackborn472ad872010-04-07 17:31:48 -07008472 static final void dumpApplicationMemoryUsage(FileDescriptor fd,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008473 PrintWriter pw, List list, String prefix, String[] args) {
Dianne Hackborn6447ca32009-04-07 19:50:08 -07008474 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008475 long uptime = SystemClock.uptimeMillis();
8476 long realtime = SystemClock.elapsedRealtime();
8477
8478 if (isCheckinRequest) {
8479 // short checkin version
8480 pw.println(uptime + "," + realtime);
8481 pw.flush();
8482 } else {
8483 pw.println("Applications Memory Usage (kB):");
8484 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
8485 }
8486 for (int i = list.size() - 1 ; i >= 0 ; i--) {
8487 ProcessRecord r = (ProcessRecord)list.get(i);
8488 if (r.thread != null) {
8489 if (!isCheckinRequest) {
8490 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
8491 pw.flush();
8492 }
8493 try {
8494 r.thread.asBinder().dump(fd, args);
8495 } catch (RemoteException e) {
8496 if (!isCheckinRequest) {
8497 pw.println("Got RemoteException!");
8498 pw.flush();
8499 }
8500 }
8501 }
8502 }
8503 }
8504
8505 /**
8506 * Searches array of arguments for the specified string
8507 * @param args array of argument strings
8508 * @param value value to search for
8509 * @return true if the value is contained in the array
8510 */
8511 private static boolean scanArgs(String[] args, String value) {
8512 if (args != null) {
8513 for (String arg : args) {
8514 if (value.equals(arg)) {
8515 return true;
8516 }
8517 }
8518 }
8519 return false;
8520 }
8521
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008522 private final void killServicesLocked(ProcessRecord app,
8523 boolean allowRestart) {
8524 // Report disconnected services.
8525 if (false) {
8526 // XXX we are letting the client link to the service for
8527 // death notifications.
8528 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008529 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008530 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008531 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008532 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008533 Iterator<ArrayList<ConnectionRecord>> jt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008534 = r.connections.values().iterator();
8535 while (jt.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008536 ArrayList<ConnectionRecord> cl = jt.next();
8537 for (int i=0; i<cl.size(); i++) {
8538 ConnectionRecord c = cl.get(i);
8539 if (c.binding.client != app) {
8540 try {
8541 //c.conn.connected(r.className, null);
8542 } catch (Exception e) {
8543 // todo: this should be asynchronous!
8544 Slog.w(TAG, "Exception thrown disconnected servce "
8545 + r.shortName
8546 + " from app " + app.processName, e);
8547 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008548 }
8549 }
8550 }
8551 }
8552 }
8553 }
8554 }
8555
8556 // Clean up any connections this application has to other services.
8557 if (app.connections.size() > 0) {
8558 Iterator<ConnectionRecord> it = app.connections.iterator();
8559 while (it.hasNext()) {
8560 ConnectionRecord r = it.next();
8561 removeConnectionLocked(r, app, null);
8562 }
8563 }
8564 app.connections.clear();
8565
8566 if (app.services.size() != 0) {
8567 // Any services running in the application need to be placed
8568 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07008569 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008570 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008571 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008572 synchronized (sr.stats.getBatteryStats()) {
8573 sr.stats.stopLaunchedLocked();
8574 }
8575 sr.app = null;
8576 sr.executeNesting = 0;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008577 if (mStoppingServices.remove(sr)) {
8578 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
8579 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008580
8581 boolean hasClients = sr.bindings.size() > 0;
8582 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008583 Iterator<IntentBindRecord> bindings
8584 = sr.bindings.values().iterator();
8585 while (bindings.hasNext()) {
8586 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08008587 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008588 + ": shouldUnbind=" + b.hasBound);
8589 b.binder = null;
8590 b.requested = b.received = b.hasBound = false;
8591 }
8592 }
8593
Dianne Hackborn070783f2010-12-29 16:46:28 -08008594 if (sr.crashCount >= 2 && (sr.serviceInfo.applicationInfo.flags
8595 &ApplicationInfo.FLAG_PERSISTENT) == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008596 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008597 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -08008598 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008599 sr.crashCount, sr.shortName, app.pid);
8600 bringDownServiceLocked(sr, true);
8601 } else if (!allowRestart) {
8602 bringDownServiceLocked(sr, true);
8603 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07008604 boolean canceled = scheduleServiceRestartLocked(sr, true);
8605
8606 // Should the service remain running? Note that in the
8607 // extreme case of so many attempts to deliver a command
8608 // that it failed, that we also will stop it here.
8609 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
8610 if (sr.pendingStarts.size() == 0) {
8611 sr.startRequested = false;
8612 if (!hasClients) {
8613 // Whoops, no reason to restart!
8614 bringDownServiceLocked(sr, true);
8615 }
8616 }
8617 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008618 }
8619 }
8620
8621 if (!allowRestart) {
8622 app.services.clear();
8623 }
8624 }
8625
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008626 // Make sure we have no more records on the stopping list.
8627 int i = mStoppingServices.size();
8628 while (i > 0) {
8629 i--;
8630 ServiceRecord sr = mStoppingServices.get(i);
8631 if (sr.app == app) {
8632 mStoppingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008633 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008634 }
8635 }
8636
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008637 app.executingServices.clear();
8638 }
8639
8640 private final void removeDyingProviderLocked(ProcessRecord proc,
8641 ContentProviderRecord cpr) {
8642 synchronized (cpr) {
8643 cpr.launchingApp = null;
8644 cpr.notifyAll();
8645 }
8646
8647 mProvidersByClass.remove(cpr.info.name);
8648 String names[] = cpr.info.authority.split(";");
8649 for (int j = 0; j < names.length; j++) {
8650 mProvidersByName.remove(names[j]);
8651 }
8652
8653 Iterator<ProcessRecord> cit = cpr.clients.iterator();
8654 while (cit.hasNext()) {
8655 ProcessRecord capp = cit.next();
8656 if (!capp.persistent && capp.thread != null
8657 && capp.pid != 0
8658 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07008659 Slog.i(TAG, "Kill " + capp.processName
8660 + " (pid " + capp.pid + "): provider " + cpr.info.name
8661 + " in dying process " + proc.processName);
8662 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
8663 capp.processName, capp.setAdj, "dying provider " + proc.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008664 Process.killProcess(capp.pid);
8665 }
8666 }
8667
8668 mLaunchingProviders.remove(cpr);
8669 }
8670
8671 /**
8672 * Main code for cleaning up a process when it has gone away. This is
8673 * called both as a result of the process dying, or directly when stopping
8674 * a process when running in single process mode.
8675 */
8676 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
8677 boolean restarting, int index) {
8678 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08008679 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008680 }
8681
Dianne Hackborn36124872009-10-08 16:22:03 -07008682 mProcessesToGc.remove(app);
8683
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008684 // Dismiss any open dialogs.
8685 if (app.crashDialog != null) {
8686 app.crashDialog.dismiss();
8687 app.crashDialog = null;
8688 }
8689 if (app.anrDialog != null) {
8690 app.anrDialog.dismiss();
8691 app.anrDialog = null;
8692 }
8693 if (app.waitDialog != null) {
8694 app.waitDialog.dismiss();
8695 app.waitDialog = null;
8696 }
8697
8698 app.crashing = false;
8699 app.notResponding = false;
8700
8701 app.resetPackageList();
8702 app.thread = null;
8703 app.forcingToForeground = null;
8704 app.foregroundServices = false;
8705
8706 killServicesLocked(app, true);
8707
8708 boolean restart = false;
8709
8710 int NL = mLaunchingProviders.size();
8711
8712 // Remove published content providers.
8713 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008714 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008715 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008716 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008717 cpr.provider = null;
8718 cpr.app = null;
8719
8720 // See if someone is waiting for this provider... in which
8721 // case we don't remove it, but just let it restart.
8722 int i = 0;
8723 if (!app.bad) {
8724 for (; i<NL; i++) {
8725 if (mLaunchingProviders.get(i) == cpr) {
8726 restart = true;
8727 break;
8728 }
8729 }
8730 } else {
8731 i = NL;
8732 }
8733
8734 if (i >= NL) {
8735 removeDyingProviderLocked(app, cpr);
8736 NL = mLaunchingProviders.size();
8737 }
8738 }
8739 app.pubProviders.clear();
8740 }
8741
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008742 // Take care of any launching providers waiting for this process.
8743 if (checkAppInLaunchingProvidersLocked(app, false)) {
8744 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008745 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008746
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008747 // Unregister from connected content providers.
8748 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07008749 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008750 while (it.hasNext()) {
8751 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
8752 cpr.clients.remove(app);
8753 }
8754 app.conProviders.clear();
8755 }
8756
Dianne Hackbornde42bb62009-08-05 12:26:15 -07008757 // At this point there may be remaining entries in mLaunchingProviders
8758 // where we were the only one waiting, so they are no longer of use.
8759 // Look for these and clean up if found.
8760 // XXX Commented out for now. Trying to figure out a way to reproduce
8761 // the actual situation to identify what is actually going on.
8762 if (false) {
8763 for (int i=0; i<NL; i++) {
8764 ContentProviderRecord cpr = (ContentProviderRecord)
8765 mLaunchingProviders.get(i);
8766 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
8767 synchronized (cpr) {
8768 cpr.launchingApp = null;
8769 cpr.notifyAll();
8770 }
8771 }
8772 }
8773 }
8774
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008775 skipCurrentReceiverLocked(app);
8776
8777 // Unregister any receivers.
8778 if (app.receivers.size() > 0) {
8779 Iterator<ReceiverList> it = app.receivers.iterator();
8780 while (it.hasNext()) {
8781 removeReceiverLocked(it.next());
8782 }
8783 app.receivers.clear();
8784 }
8785
Christopher Tate181fafa2009-05-14 11:12:14 -07008786 // If the app is undergoing backup, tell the backup manager about it
8787 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008788 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -07008789 try {
8790 IBackupManager bm = IBackupManager.Stub.asInterface(
8791 ServiceManager.getService(Context.BACKUP_SERVICE));
8792 bm.agentDisconnected(app.info.packageName);
8793 } catch (RemoteException e) {
8794 // can't happen; backup manager is local
8795 }
8796 }
8797
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008798 // If the caller is restarting this app, then leave it in its
8799 // current lists and let the caller take care of it.
8800 if (restarting) {
8801 return;
8802 }
8803
8804 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008805 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008806 "Removing non-persistent process during cleanup: " + app);
8807 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07008808 if (mHeavyWeightProcess == app) {
8809 mHeavyWeightProcess = null;
8810 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
8811 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008812 } else if (!app.removed) {
8813 // This app is persistent, so we need to keep its record around.
8814 // If it is not already on the pending app list, add it there
8815 // and start a new process for it.
8816 app.thread = null;
8817 app.forcingToForeground = null;
8818 app.foregroundServices = false;
8819 if (mPersistentStartingProcesses.indexOf(app) < 0) {
8820 mPersistentStartingProcesses.add(app);
8821 restart = true;
8822 }
8823 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07008824 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
8825 "Clean-up removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008826 mProcessesOnHold.remove(app);
8827
The Android Open Source Project4df24232009-03-05 14:34:35 -08008828 if (app == mHomeProcess) {
8829 mHomeProcess = null;
8830 }
8831
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008832 if (restart) {
8833 // We have components that still need to be running in the
8834 // process, so re-launch it.
8835 mProcessNames.put(app.processName, app.info.uid, app);
8836 startProcessLocked(app, "restart", app.processName);
8837 } else if (app.pid > 0 && app.pid != MY_PID) {
8838 // Goodbye!
8839 synchronized (mPidsSelfLocked) {
8840 mPidsSelfLocked.remove(app.pid);
8841 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
8842 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008843 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008844 }
8845 }
8846
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008847 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
8848 // Look through the content providers we are waiting to have launched,
8849 // and if any run in this process then either schedule a restart of
8850 // the process or kill the client waiting for it if this process has
8851 // gone bad.
8852 int NL = mLaunchingProviders.size();
8853 boolean restart = false;
8854 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008855 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08008856 if (cpr.launchingApp == app) {
8857 if (!alwaysBad && !app.bad) {
8858 restart = true;
8859 } else {
8860 removeDyingProviderLocked(app, cpr);
8861 NL = mLaunchingProviders.size();
8862 }
8863 }
8864 }
8865 return restart;
8866 }
8867
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008868 // =========================================================
8869 // SERVICES
8870 // =========================================================
8871
8872 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
8873 ActivityManager.RunningServiceInfo info =
8874 new ActivityManager.RunningServiceInfo();
8875 info.service = r.name;
8876 if (r.app != null) {
8877 info.pid = r.app.pid;
8878 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008879 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008880 info.process = r.processName;
8881 info.foreground = r.isForeground;
8882 info.activeSince = r.createTime;
8883 info.started = r.startRequested;
8884 info.clientCount = r.connections.size();
8885 info.crashCount = r.crashCount;
8886 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008887 if (r.isForeground) {
8888 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
8889 }
8890 if (r.startRequested) {
8891 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
8892 }
Dan Egnor42471dd2010-01-07 17:25:22 -08008893 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -07008894 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
8895 }
8896 if (r.app != null && r.app.persistent) {
8897 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
8898 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008899
8900 for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
8901 for (int i=0; i<connl.size(); i++) {
8902 ConnectionRecord conn = connl.get(i);
8903 if (conn.clientLabel != 0) {
8904 info.clientPackage = conn.binding.client.info.packageName;
8905 info.clientLabel = conn.clientLabel;
8906 return info;
8907 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008908 }
8909 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008910 return info;
8911 }
8912
8913 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
8914 int flags) {
8915 synchronized (this) {
8916 ArrayList<ActivityManager.RunningServiceInfo> res
8917 = new ArrayList<ActivityManager.RunningServiceInfo>();
8918
8919 if (mServices.size() > 0) {
8920 Iterator<ServiceRecord> it = mServices.values().iterator();
8921 while (it.hasNext() && res.size() < maxNum) {
8922 res.add(makeRunningServiceInfoLocked(it.next()));
8923 }
8924 }
8925
8926 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
8927 ServiceRecord r = mRestartingServices.get(i);
8928 ActivityManager.RunningServiceInfo info =
8929 makeRunningServiceInfoLocked(r);
8930 info.restarting = r.nextRestartTime;
8931 res.add(info);
8932 }
8933
8934 return res;
8935 }
8936 }
8937
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008938 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
8939 synchronized (this) {
8940 ServiceRecord r = mServices.get(name);
8941 if (r != null) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008942 for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
8943 for (int i=0; i<conn.size(); i++) {
8944 if (conn.get(i).clientIntent != null) {
8945 return conn.get(i).clientIntent;
8946 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008947 }
8948 }
8949 }
8950 }
8951 return null;
8952 }
8953
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008954 private final ServiceRecord findServiceLocked(ComponentName name,
8955 IBinder token) {
8956 ServiceRecord r = mServices.get(name);
8957 return r == token ? r : null;
8958 }
8959
8960 private final class ServiceLookupResult {
8961 final ServiceRecord record;
8962 final String permission;
8963
8964 ServiceLookupResult(ServiceRecord _record, String _permission) {
8965 record = _record;
8966 permission = _permission;
8967 }
8968 };
8969
8970 private ServiceLookupResult findServiceLocked(Intent service,
8971 String resolvedType) {
8972 ServiceRecord r = null;
8973 if (service.getComponent() != null) {
8974 r = mServices.get(service.getComponent());
8975 }
8976 if (r == null) {
8977 Intent.FilterComparison filter = new Intent.FilterComparison(service);
8978 r = mServicesByIntent.get(filter);
8979 }
8980
8981 if (r == null) {
8982 try {
8983 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008984 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008985 service, resolvedType, 0);
8986 ServiceInfo sInfo =
8987 rInfo != null ? rInfo.serviceInfo : null;
8988 if (sInfo == null) {
8989 return null;
8990 }
8991
8992 ComponentName name = new ComponentName(
8993 sInfo.applicationInfo.packageName, sInfo.name);
8994 r = mServices.get(name);
8995 } catch (RemoteException ex) {
8996 // pm is in same process, this will never happen.
8997 }
8998 }
8999 if (r != null) {
9000 int callingPid = Binder.getCallingPid();
9001 int callingUid = Binder.getCallingUid();
9002 if (checkComponentPermission(r.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009003 callingPid, callingUid, r.appInfo.uid, r.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009004 != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009005 if (!r.exported) {
9006 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
9007 + " from pid=" + callingPid
9008 + ", uid=" + callingUid
9009 + " that is not exported from uid " + r.appInfo.uid);
9010 return new ServiceLookupResult(null, "not exported from uid "
9011 + r.appInfo.uid);
9012 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009013 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009014 + " from pid=" + callingPid
9015 + ", uid=" + callingUid
9016 + " requires " + r.permission);
9017 return new ServiceLookupResult(null, r.permission);
9018 }
9019 return new ServiceLookupResult(r, null);
9020 }
9021 return null;
9022 }
9023
9024 private class ServiceRestarter implements Runnable {
9025 private ServiceRecord mService;
9026
9027 void setService(ServiceRecord service) {
9028 mService = service;
9029 }
9030
9031 public void run() {
9032 synchronized(ActivityManagerService.this) {
9033 performServiceRestartLocked(mService);
9034 }
9035 }
9036 }
9037
9038 private ServiceLookupResult retrieveServiceLocked(Intent service,
9039 String resolvedType, int callingPid, int callingUid) {
9040 ServiceRecord r = null;
9041 if (service.getComponent() != null) {
9042 r = mServices.get(service.getComponent());
9043 }
9044 Intent.FilterComparison filter = new Intent.FilterComparison(service);
9045 r = mServicesByIntent.get(filter);
9046 if (r == null) {
9047 try {
9048 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009049 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -07009050 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009051 ServiceInfo sInfo =
9052 rInfo != null ? rInfo.serviceInfo : null;
9053 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009054 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009055 ": not found");
9056 return null;
9057 }
9058
9059 ComponentName name = new ComponentName(
9060 sInfo.applicationInfo.packageName, sInfo.name);
9061 r = mServices.get(name);
9062 if (r == null) {
9063 filter = new Intent.FilterComparison(service.cloneFilter());
9064 ServiceRestarter res = new ServiceRestarter();
9065 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
9066 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
9067 synchronized (stats) {
9068 ss = stats.getServiceStatsLocked(
9069 sInfo.applicationInfo.uid, sInfo.packageName,
9070 sInfo.name);
9071 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -08009072 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009073 res.setService(r);
9074 mServices.put(name, r);
9075 mServicesByIntent.put(filter, r);
9076
9077 // Make sure this component isn't in the pending list.
9078 int N = mPendingServices.size();
9079 for (int i=0; i<N; i++) {
9080 ServiceRecord pr = mPendingServices.get(i);
9081 if (pr.name.equals(name)) {
9082 mPendingServices.remove(i);
9083 i--;
9084 N--;
9085 }
9086 }
9087 }
9088 } catch (RemoteException ex) {
9089 // pm is in same process, this will never happen.
9090 }
9091 }
9092 if (r != null) {
9093 if (checkComponentPermission(r.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009094 callingPid, callingUid, r.appInfo.uid, r.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009095 != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009096 if (!r.exported) {
9097 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
9098 + " from pid=" + callingPid
9099 + ", uid=" + callingUid
9100 + " that is not exported from uid " + r.appInfo.uid);
9101 return new ServiceLookupResult(null, "not exported from uid "
9102 + r.appInfo.uid);
9103 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009104 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009105 + " from pid=" + callingPid
9106 + ", uid=" + callingUid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009107 + " requires " + r.permission);
9108 return new ServiceLookupResult(null, r.permission);
9109 }
9110 return new ServiceLookupResult(r, null);
9111 }
9112 return null;
9113 }
9114
Dianne Hackborn287952c2010-09-22 22:34:31 -07009115 private final void bumpServiceExecutingLocked(ServiceRecord r, String why) {
9116 if (DEBUG_SERVICE) Log.v(TAG, ">>> EXECUTING "
9117 + why + " of " + r + " in app " + r.app);
9118 else if (DEBUG_SERVICE_EXECUTING) Log.v(TAG, ">>> EXECUTING "
9119 + why + " of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009120 long now = SystemClock.uptimeMillis();
9121 if (r.executeNesting == 0 && r.app != null) {
9122 if (r.app.executingServices.size() == 0) {
9123 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
9124 msg.obj = r.app;
9125 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
9126 }
9127 r.app.executingServices.add(r);
9128 }
9129 r.executeNesting++;
9130 r.executingStart = now;
9131 }
9132
9133 private final void sendServiceArgsLocked(ServiceRecord r,
9134 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009135 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009136 if (N == 0) {
9137 return;
9138 }
9139
Dianne Hackborn39792d22010-08-19 18:01:52 -07009140 while (r.pendingStarts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009141 try {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009142 ServiceRecord.StartItem si = r.pendingStarts.remove(0);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009143 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
9144 + r + " " + r.intent + " args=" + si.intent);
Dianne Hackborn3a28f222011-03-01 12:25:54 -08009145 if (si.intent == null && N > 1) {
9146 // If somehow we got a dummy null intent in the middle,
9147 // then skip it. DO NOT skip a null intent when it is
9148 // the only one in the list -- this is to support the
9149 // onStartCommand(null) case.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009150 continue;
9151 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009152 si.deliveredTime = SystemClock.uptimeMillis();
9153 r.deliveredStarts.add(si);
9154 si.deliveryCount++;
Dianne Hackborn3a28f222011-03-01 12:25:54 -08009155 if (si.targetPermissionUid >= 0 && si.intent != null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009156 grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
Dianne Hackborn7e269642010-08-25 19:50:20 -07009157 r.packageName, si.intent, si.getUriPermissionsLocked());
Dianne Hackborn39792d22010-08-19 18:01:52 -07009158 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07009159 bumpServiceExecutingLocked(r, "start");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009160 if (!oomAdjusted) {
9161 oomAdjusted = true;
9162 updateOomAdjLocked(r.app);
9163 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009164 int flags = 0;
9165 if (si.deliveryCount > 0) {
9166 flags |= Service.START_FLAG_RETRY;
9167 }
9168 if (si.doneExecutingCount > 0) {
9169 flags |= Service.START_FLAG_REDELIVERY;
9170 }
9171 r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009172 } catch (RemoteException e) {
9173 // Remote process gone... we'll let the normal cleanup take
9174 // care of this.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009175 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009176 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009177 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009178 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009179 break;
9180 }
9181 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009182 }
9183
9184 private final boolean requestServiceBindingLocked(ServiceRecord r,
9185 IntentBindRecord i, boolean rebind) {
9186 if (r.app == null || r.app.thread == null) {
9187 // If service is not currently running, can't yet bind.
9188 return false;
9189 }
9190 if ((!i.requested || rebind) && i.apps.size() > 0) {
9191 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009192 bumpServiceExecutingLocked(r, "bind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009193 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
9194 if (!rebind) {
9195 i.requested = true;
9196 }
9197 i.hasBound = true;
9198 i.doRebind = false;
9199 } catch (RemoteException e) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009200 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009201 return false;
9202 }
9203 }
9204 return true;
9205 }
9206
9207 private final void requestServiceBindingsLocked(ServiceRecord r) {
9208 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
9209 while (bindings.hasNext()) {
9210 IntentBindRecord i = bindings.next();
9211 if (!requestServiceBindingLocked(r, i, false)) {
9212 break;
9213 }
9214 }
9215 }
9216
9217 private final void realStartServiceLocked(ServiceRecord r,
9218 ProcessRecord app) throws RemoteException {
9219 if (app.thread == null) {
9220 throw new RemoteException();
9221 }
9222
9223 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -07009224 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009225
9226 app.services.add(r);
Dianne Hackborn287952c2010-09-22 22:34:31 -07009227 bumpServiceExecutingLocked(r, "create");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009228 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009229
9230 boolean created = false;
9231 try {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07009232 mStringBuilder.setLength(0);
9233 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009234 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009235 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -07009236 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009237 synchronized (r.stats.getBatteryStats()) {
9238 r.stats.startLaunchedLocked();
9239 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07009240 ensurePackageDexOpt(r.serviceInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009241 app.thread.scheduleCreateService(r, r.serviceInfo);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009242 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009243 created = true;
9244 } finally {
9245 if (!created) {
9246 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009247 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009248 }
9249 }
9250
9251 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009252
9253 // If the service is in the started state, and there are no
9254 // pending arguments, then fake up one so its onStartCommand() will
9255 // be called.
9256 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
9257 r.lastStartId++;
9258 if (r.lastStartId < 1) {
9259 r.lastStartId = 1;
9260 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009261 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId, null, -1));
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009262 }
9263
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009264 sendServiceArgsLocked(r, true);
9265 }
9266
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009267 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
9268 boolean allowCancel) {
9269 boolean canceled = false;
9270
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009271 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009272 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -07009273 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009274
Dianne Hackborn070783f2010-12-29 16:46:28 -08009275 if ((r.serviceInfo.applicationInfo.flags
9276 &ApplicationInfo.FLAG_PERSISTENT) != 0) {
9277 minDuration /= 4;
9278 }
9279
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009280 // Any delivered but not yet finished starts should be put back
9281 // on the pending list.
9282 final int N = r.deliveredStarts.size();
9283 if (N > 0) {
9284 for (int i=N-1; i>=0; i--) {
9285 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
Dianne Hackborn39792d22010-08-19 18:01:52 -07009286 si.removeUriPermissionsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009287 if (si.intent == null) {
9288 // We'll generate this again if needed.
9289 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
9290 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
9291 r.pendingStarts.add(0, si);
9292 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
9293 dur *= 2;
9294 if (minDuration < dur) minDuration = dur;
9295 if (resetTime < dur) resetTime = dur;
9296 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009297 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009298 + r.name);
9299 canceled = true;
9300 }
9301 }
9302 r.deliveredStarts.clear();
9303 }
9304
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009305 r.totalRestartCount++;
9306 if (r.restartDelay == 0) {
9307 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009308 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009309 } else {
9310 // If it has been a "reasonably long time" since the service
9311 // was started, then reset our restart duration back to
9312 // the beginning, so we don't infinitely increase the duration
9313 // on a service that just occasionally gets killed (which is
9314 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009315 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009316 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009317 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009318 } else {
Dianne Hackborn070783f2010-12-29 16:46:28 -08009319 if ((r.serviceInfo.applicationInfo.flags
9320 &ApplicationInfo.FLAG_PERSISTENT) != 0) {
9321 // Services in peristent processes will restart much more
9322 // quickly, since they are pretty important. (Think SystemUI).
9323 r.restartDelay += minDuration/2;
9324 } else {
9325 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
9326 if (r.restartDelay < minDuration) {
9327 r.restartDelay = minDuration;
9328 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009329 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009330 }
9331 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009332
9333 r.nextRestartTime = now + r.restartDelay;
9334
9335 // Make sure that we don't end up restarting a bunch of services
9336 // all at the same time.
9337 boolean repeat;
9338 do {
9339 repeat = false;
9340 for (int i=mRestartingServices.size()-1; i>=0; i--) {
9341 ServiceRecord r2 = mRestartingServices.get(i);
9342 if (r2 != r && r.nextRestartTime
9343 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
9344 && r.nextRestartTime
9345 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
9346 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
9347 r.restartDelay = r.nextRestartTime - now;
9348 repeat = true;
9349 break;
9350 }
9351 }
9352 } while (repeat);
9353
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009354 if (!mRestartingServices.contains(r)) {
9355 mRestartingServices.add(r);
9356 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009357
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009358 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009359
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009360 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009361 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009362 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009363 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009364 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -08009365 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009366 r.shortName, r.restartDelay);
9367
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009368 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009369 }
9370
9371 final void performServiceRestartLocked(ServiceRecord r) {
9372 if (!mRestartingServices.contains(r)) {
9373 return;
9374 }
9375 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
9376 }
9377
9378 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
9379 if (r.restartDelay == 0) {
9380 return false;
9381 }
9382 r.resetRestartCounter();
9383 mRestartingServices.remove(r);
9384 mHandler.removeCallbacks(r.restarter);
9385 return true;
9386 }
9387
9388 private final boolean bringUpServiceLocked(ServiceRecord r,
9389 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009390 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009391 //r.dump(" ");
9392
Dianne Hackborn36124872009-10-08 16:22:03 -07009393 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009394 sendServiceArgsLocked(r, false);
9395 return true;
9396 }
9397
9398 if (!whileRestarting && r.restartDelay > 0) {
9399 // If waiting for a restart, then do nothing.
9400 return true;
9401 }
9402
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009403 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009404
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009405 // We are now bringing the service up, so no longer in the
9406 // restarting state.
9407 mRestartingServices.remove(r);
9408
Dianne Hackborne7f97212011-02-24 14:40:20 -08009409 // Service is now being launched, its package can't be stopped.
9410 try {
9411 AppGlobals.getPackageManager().setPackageStoppedState(
9412 r.packageName, false);
9413 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08009414 } catch (IllegalArgumentException e) {
9415 Slog.w(TAG, "Failed trying to unstop package "
9416 + r.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08009417 }
9418
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009419 final String appName = r.processName;
9420 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
9421 if (app != null && app.thread != null) {
9422 try {
9423 realStartServiceLocked(r, app);
9424 return true;
9425 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009426 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009427 }
9428
9429 // If a dead object exception was thrown -- fall through to
9430 // restart the application.
9431 }
9432
Dianne Hackborn36124872009-10-08 16:22:03 -07009433 // Not running -- get it started, and enqueue this service record
9434 // to be executed when the app comes up.
9435 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
9436 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009437 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -07009438 + r.appInfo.packageName + "/"
9439 + r.appInfo.uid + " for service "
9440 + r.intent.getIntent() + ": process is bad");
9441 bringDownServiceLocked(r, true);
9442 return false;
9443 }
9444
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009445 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009446 mPendingServices.add(r);
9447 }
Dianne Hackborn36124872009-10-08 16:22:03 -07009448
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009449 return true;
9450 }
9451
9452 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009453 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009454 //r.dump(" ");
9455
9456 // Does it still need to run?
9457 if (!force && r.startRequested) {
9458 return;
9459 }
9460 if (r.connections.size() > 0) {
9461 if (!force) {
9462 // XXX should probably keep a count of the number of auto-create
9463 // connections directly in the service.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009464 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009465 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009466 ArrayList<ConnectionRecord> cr = it.next();
9467 for (int i=0; i<cr.size(); i++) {
9468 if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
9469 return;
9470 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009471 }
9472 }
9473 }
9474
9475 // Report to all of the connections that the service is no longer
9476 // available.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009477 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009478 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009479 ArrayList<ConnectionRecord> c = it.next();
9480 for (int i=0; i<c.size(); i++) {
9481 try {
9482 c.get(i).conn.connected(r.name, null);
9483 } catch (Exception e) {
9484 Slog.w(TAG, "Failure disconnecting service " + r.name +
9485 " to connection " + c.get(i).conn.asBinder() +
9486 " (in " + c.get(i).binding.client.processName + ")", e);
9487 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009488 }
9489 }
9490 }
9491
9492 // Tell the service that it has been unbound.
9493 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
9494 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
9495 while (it.hasNext()) {
9496 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009497 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009498 + ": hasBound=" + ibr.hasBound);
9499 if (r.app != null && r.app.thread != null && ibr.hasBound) {
9500 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009501 bumpServiceExecutingLocked(r, "bring down unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009502 updateOomAdjLocked(r.app);
9503 ibr.hasBound = false;
9504 r.app.thread.scheduleUnbindService(r,
9505 ibr.intent.getIntent());
9506 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009507 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009508 + r.shortName, e);
9509 serviceDoneExecutingLocked(r, true);
9510 }
9511 }
9512 }
9513 }
9514
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009515 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009516 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009517 System.identityHashCode(r), r.shortName,
9518 (r.app != null) ? r.app.pid : -1);
9519
9520 mServices.remove(r.name);
9521 mServicesByIntent.remove(r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009522 r.totalRestartCount = 0;
9523 unscheduleServiceRestartLocked(r);
9524
9525 // Also make sure it is not on the pending list.
9526 int N = mPendingServices.size();
9527 for (int i=0; i<N; i++) {
9528 if (mPendingServices.get(i) == r) {
9529 mPendingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009530 if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009531 i--;
9532 N--;
9533 }
9534 }
9535
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009536 r.cancelNotification();
9537 r.isForeground = false;
9538 r.foregroundId = 0;
9539 r.foregroundNoti = null;
9540
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009541 // Clear start entries.
Dianne Hackborn39792d22010-08-19 18:01:52 -07009542 r.clearDeliveredStartsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009543 r.pendingStarts.clear();
9544
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009545 if (r.app != null) {
9546 synchronized (r.stats.getBatteryStats()) {
9547 r.stats.stopLaunchedLocked();
9548 }
9549 r.app.services.remove(r);
9550 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009551 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009552 bumpServiceExecutingLocked(r, "stop");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009553 mStoppingServices.add(r);
9554 updateOomAdjLocked(r.app);
9555 r.app.thread.scheduleStopService(r);
9556 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009557 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009558 + r.shortName, e);
9559 serviceDoneExecutingLocked(r, true);
9560 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009561 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009562 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009563 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009564 TAG, "Removed service that has no process: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009565 }
9566 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009567 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009568 TAG, "Removed service that is not running: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009569 }
Vairavan Srinivasana207ce22010-12-23 13:51:48 -08009570
9571 if (r.bindings.size() > 0) {
9572 r.bindings.clear();
9573 }
9574
9575 if (r.restarter instanceof ServiceRestarter) {
9576 ((ServiceRestarter)r.restarter).setService(null);
9577 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009578 }
9579
9580 ComponentName startServiceLocked(IApplicationThread caller,
9581 Intent service, String resolvedType,
9582 int callingPid, int callingUid) {
9583 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009584 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009585 + " type=" + resolvedType + " args=" + service.getExtras());
9586
9587 if (caller != null) {
9588 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9589 if (callerApp == null) {
9590 throw new SecurityException(
9591 "Unable to find app for caller " + caller
9592 + " (pid=" + Binder.getCallingPid()
9593 + ") when starting service " + service);
9594 }
9595 }
9596
9597 ServiceLookupResult res =
9598 retrieveServiceLocked(service, resolvedType,
9599 callingPid, callingUid);
9600 if (res == null) {
9601 return null;
9602 }
9603 if (res.record == null) {
9604 return new ComponentName("!", res.permission != null
9605 ? res.permission : "private to package");
9606 }
9607 ServiceRecord r = res.record;
Dianne Hackborn39792d22010-08-19 18:01:52 -07009608 int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
9609 callingUid, r.packageName, service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009610 if (unscheduleServiceRestartLocked(r)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009611 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009612 }
9613 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009614 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009615 r.lastStartId++;
9616 if (r.lastStartId < 1) {
9617 r.lastStartId = 1;
9618 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009619 r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId,
9620 service, targetPermissionUid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009621 r.lastActivity = SystemClock.uptimeMillis();
9622 synchronized (r.stats.getBatteryStats()) {
9623 r.stats.startRunningLocked();
9624 }
9625 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
9626 return new ComponentName("!", "Service process is bad");
9627 }
9628 return r.name;
9629 }
9630 }
9631
9632 public ComponentName startService(IApplicationThread caller, Intent service,
9633 String resolvedType) {
9634 // Refuse possible leaked file descriptors
9635 if (service != null && service.hasFileDescriptors() == true) {
9636 throw new IllegalArgumentException("File descriptors passed in Intent");
9637 }
9638
9639 synchronized(this) {
9640 final int callingPid = Binder.getCallingPid();
9641 final int callingUid = Binder.getCallingUid();
9642 final long origId = Binder.clearCallingIdentity();
9643 ComponentName res = startServiceLocked(caller, service,
9644 resolvedType, callingPid, callingUid);
9645 Binder.restoreCallingIdentity(origId);
9646 return res;
9647 }
9648 }
9649
9650 ComponentName startServiceInPackage(int uid,
9651 Intent service, String resolvedType) {
9652 synchronized(this) {
9653 final long origId = Binder.clearCallingIdentity();
9654 ComponentName res = startServiceLocked(null, service,
9655 resolvedType, -1, uid);
9656 Binder.restoreCallingIdentity(origId);
9657 return res;
9658 }
9659 }
9660
9661 public int stopService(IApplicationThread caller, Intent service,
9662 String resolvedType) {
9663 // Refuse possible leaked file descriptors
9664 if (service != null && service.hasFileDescriptors() == true) {
9665 throw new IllegalArgumentException("File descriptors passed in Intent");
9666 }
9667
9668 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009669 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009670 + " type=" + resolvedType);
9671
9672 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9673 if (caller != null && callerApp == null) {
9674 throw new SecurityException(
9675 "Unable to find app for caller " + caller
9676 + " (pid=" + Binder.getCallingPid()
9677 + ") when stopping service " + service);
9678 }
9679
9680 // If this service is active, make sure it is stopped.
9681 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9682 if (r != null) {
9683 if (r.record != null) {
9684 synchronized (r.record.stats.getBatteryStats()) {
9685 r.record.stats.stopRunningLocked();
9686 }
9687 r.record.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009688 r.record.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009689 final long origId = Binder.clearCallingIdentity();
9690 bringDownServiceLocked(r.record, false);
9691 Binder.restoreCallingIdentity(origId);
9692 return 1;
9693 }
9694 return -1;
9695 }
9696 }
9697
9698 return 0;
9699 }
9700
9701 public IBinder peekService(Intent service, String resolvedType) {
9702 // Refuse possible leaked file descriptors
9703 if (service != null && service.hasFileDescriptors() == true) {
9704 throw new IllegalArgumentException("File descriptors passed in Intent");
9705 }
9706
9707 IBinder ret = null;
9708
9709 synchronized(this) {
9710 ServiceLookupResult r = findServiceLocked(service, resolvedType);
9711
9712 if (r != null) {
9713 // r.record is null if findServiceLocked() failed the caller permission check
9714 if (r.record == null) {
9715 throw new SecurityException(
9716 "Permission Denial: Accessing service " + r.record.name
9717 + " from pid=" + Binder.getCallingPid()
9718 + ", uid=" + Binder.getCallingUid()
9719 + " requires " + r.permission);
9720 }
9721 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
9722 if (ib != null) {
9723 ret = ib.binder;
9724 }
9725 }
9726 }
9727
9728 return ret;
9729 }
9730
9731 public boolean stopServiceToken(ComponentName className, IBinder token,
9732 int startId) {
9733 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009734 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009735 + " " + token + " startId=" + startId);
9736 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009737 if (r != null) {
9738 if (startId >= 0) {
9739 // Asked to only stop if done with all work. Note that
9740 // to avoid leaks, we will take this as dropping all
9741 // start items up to and including this one.
9742 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
9743 if (si != null) {
9744 while (r.deliveredStarts.size() > 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009745 ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
9746 cur.removeUriPermissionsLocked();
9747 if (cur == si) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009748 break;
9749 }
9750 }
9751 }
9752
9753 if (r.lastStartId != startId) {
9754 return false;
9755 }
9756
9757 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009758 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009759 + " is last, but have " + r.deliveredStarts.size()
9760 + " remaining args");
9761 }
9762 }
9763
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009764 synchronized (r.stats.getBatteryStats()) {
9765 r.stats.stopRunningLocked();
9766 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009767 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009768 }
9769 final long origId = Binder.clearCallingIdentity();
9770 bringDownServiceLocked(r, false);
9771 Binder.restoreCallingIdentity(origId);
9772 return true;
9773 }
9774 }
9775 return false;
9776 }
9777
9778 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009779 int id, Notification notification, boolean removeNotification) {
9780 final long origId = Binder.clearCallingIdentity();
9781 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009782 synchronized(this) {
9783 ServiceRecord r = findServiceLocked(className, token);
9784 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009785 if (id != 0) {
9786 if (notification == null) {
9787 throw new IllegalArgumentException("null notification");
9788 }
9789 if (r.foregroundId != id) {
9790 r.cancelNotification();
9791 r.foregroundId = id;
9792 }
9793 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
9794 r.foregroundNoti = notification;
9795 r.isForeground = true;
9796 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009797 if (r.app != null) {
9798 updateServiceForegroundLocked(r.app, true);
9799 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009800 } else {
9801 if (r.isForeground) {
9802 r.isForeground = false;
9803 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07009804 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009805 updateServiceForegroundLocked(r.app, true);
9806 }
9807 }
9808 if (removeNotification) {
9809 r.cancelNotification();
9810 r.foregroundId = 0;
9811 r.foregroundNoti = null;
9812 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009813 }
9814 }
9815 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009816 } finally {
9817 Binder.restoreCallingIdentity(origId);
9818 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009819 }
9820
9821 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
9822 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -07009823 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009824 if (sr.isForeground) {
9825 anyForeground = true;
9826 break;
9827 }
9828 }
9829 if (anyForeground != proc.foregroundServices) {
9830 proc.foregroundServices = anyForeground;
9831 if (oomAdj) {
9832 updateOomAdjLocked();
9833 }
9834 }
9835 }
9836
9837 public int bindService(IApplicationThread caller, IBinder token,
9838 Intent service, String resolvedType,
9839 IServiceConnection connection, int flags) {
9840 // Refuse possible leaked file descriptors
9841 if (service != null && service.hasFileDescriptors() == true) {
9842 throw new IllegalArgumentException("File descriptors passed in Intent");
9843 }
9844
9845 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009846 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009847 + " type=" + resolvedType + " conn=" + connection.asBinder()
9848 + " flags=0x" + Integer.toHexString(flags));
9849 final ProcessRecord callerApp = getRecordForAppLocked(caller);
9850 if (callerApp == null) {
9851 throw new SecurityException(
9852 "Unable to find app for caller " + caller
9853 + " (pid=" + Binder.getCallingPid()
9854 + ") when binding service " + service);
9855 }
9856
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009857 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009858 if (token != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009859 int aindex = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009860 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009861 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009862 return 0;
9863 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009864 activity = (ActivityRecord)mMainStack.mHistory.get(aindex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009865 }
9866
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009867 int clientLabel = 0;
9868 PendingIntent clientIntent = null;
9869
9870 if (callerApp.info.uid == Process.SYSTEM_UID) {
9871 // Hacky kind of thing -- allow system stuff to tell us
9872 // what they are, so we can report this elsewhere for
9873 // others to know why certain services are running.
9874 try {
9875 clientIntent = (PendingIntent)service.getParcelableExtra(
9876 Intent.EXTRA_CLIENT_INTENT);
9877 } catch (RuntimeException e) {
9878 }
9879 if (clientIntent != null) {
9880 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
9881 if (clientLabel != 0) {
9882 // There are no useful extras in the intent, trash them.
9883 // System code calling with this stuff just needs to know
9884 // this will happen.
9885 service = service.cloneFilter();
9886 }
9887 }
9888 }
9889
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009890 ServiceLookupResult res =
9891 retrieveServiceLocked(service, resolvedType,
9892 Binder.getCallingPid(), Binder.getCallingUid());
9893 if (res == null) {
9894 return 0;
9895 }
9896 if (res.record == null) {
9897 return -1;
9898 }
9899 ServiceRecord s = res.record;
9900
9901 final long origId = Binder.clearCallingIdentity();
9902
9903 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009904 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009905 + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009906 }
9907
9908 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
9909 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009910 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009911
9912 IBinder binder = connection.asBinder();
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009913 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9914 if (clist == null) {
9915 clist = new ArrayList<ConnectionRecord>();
9916 s.connections.put(binder, clist);
9917 }
9918 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009919 b.connections.add(c);
9920 if (activity != null) {
9921 if (activity.connections == null) {
9922 activity.connections = new HashSet<ConnectionRecord>();
9923 }
9924 activity.connections.add(c);
9925 }
9926 b.client.connections.add(c);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009927 clist = mServiceConnections.get(binder);
9928 if (clist == null) {
9929 clist = new ArrayList<ConnectionRecord>();
9930 mServiceConnections.put(binder, clist);
9931 }
9932 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009933
9934 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
9935 s.lastActivity = SystemClock.uptimeMillis();
9936 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
9937 return 0;
9938 }
9939 }
9940
9941 if (s.app != null) {
9942 // This could have made the service more important.
9943 updateOomAdjLocked(s.app);
9944 }
9945
Joe Onorato8a9b2202010-02-26 18:56:32 -08009946 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009947 + ": received=" + b.intent.received
9948 + " apps=" + b.intent.apps.size()
9949 + " doRebind=" + b.intent.doRebind);
9950
9951 if (s.app != null && b.intent.received) {
9952 // Service is already running, so we can immediately
9953 // publish the connection.
9954 try {
9955 c.conn.connected(s.name, b.intent.binder);
9956 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009957 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009958 + " to connection " + c.conn.asBinder()
9959 + " (in " + c.binding.client.processName + ")", e);
9960 }
9961
9962 // If this is the first app connected back to this binding,
9963 // and the service had previously asked to be told when
9964 // rebound, then do so.
9965 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
9966 requestServiceBindingLocked(s, b.intent, true);
9967 }
9968 } else if (!b.intent.requested) {
9969 requestServiceBindingLocked(s, b.intent, false);
9970 }
9971
9972 Binder.restoreCallingIdentity(origId);
9973 }
9974
9975 return 1;
9976 }
9977
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07009978 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009979 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009980 IBinder binder = c.conn.asBinder();
9981 AppBindRecord b = c.binding;
9982 ServiceRecord s = b.service;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009983 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
9984 if (clist != null) {
9985 clist.remove(c);
9986 if (clist.size() == 0) {
9987 s.connections.remove(binder);
9988 }
9989 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009990 b.connections.remove(c);
9991 if (c.activity != null && c.activity != skipAct) {
9992 if (c.activity.connections != null) {
9993 c.activity.connections.remove(c);
9994 }
9995 }
9996 if (b.client != skipApp) {
9997 b.client.connections.remove(c);
9998 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009999 clist = mServiceConnections.get(binder);
10000 if (clist != null) {
10001 clist.remove(c);
10002 if (clist.size() == 0) {
10003 mServiceConnections.remove(binder);
10004 }
10005 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010006
10007 if (b.connections.size() == 0) {
10008 b.intent.apps.remove(b.client);
10009 }
10010
Joe Onorato8a9b2202010-02-26 18:56:32 -080010011 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010012 + ": shouldUnbind=" + b.intent.hasBound);
10013 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
10014 && b.intent.hasBound) {
10015 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010016 bumpServiceExecutingLocked(s, "unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010017 updateOomAdjLocked(s.app);
10018 b.intent.hasBound = false;
10019 // Assume the client doesn't want to know about a rebind;
10020 // we will deal with that later if it asks for one.
10021 b.intent.doRebind = false;
10022 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
10023 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010024 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010025 serviceDoneExecutingLocked(s, true);
10026 }
10027 }
10028
10029 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
10030 bringDownServiceLocked(s, false);
10031 }
10032 }
10033
10034 public boolean unbindService(IServiceConnection connection) {
10035 synchronized (this) {
10036 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010037 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010038 ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
10039 if (clist == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010040 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010041 + connection.asBinder());
10042 return false;
10043 }
10044
10045 final long origId = Binder.clearCallingIdentity();
10046
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010047 while (clist.size() > 0) {
10048 ConnectionRecord r = clist.get(0);
10049 removeConnectionLocked(r, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010050
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010051 if (r.binding.service.app != null) {
10052 // This could have made the service less important.
10053 updateOomAdjLocked(r.binding.service.app);
10054 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010055 }
10056
10057 Binder.restoreCallingIdentity(origId);
10058 }
10059
10060 return true;
10061 }
10062
10063 public void publishService(IBinder token, Intent intent, IBinder service) {
10064 // Refuse possible leaked file descriptors
10065 if (intent != null && intent.hasFileDescriptors() == true) {
10066 throw new IllegalArgumentException("File descriptors passed in Intent");
10067 }
10068
10069 synchronized(this) {
10070 if (!(token instanceof ServiceRecord)) {
10071 throw new IllegalArgumentException("Invalid service token");
10072 }
10073 ServiceRecord r = (ServiceRecord)token;
10074
10075 final long origId = Binder.clearCallingIdentity();
10076
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010077 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010078 + " " + intent + ": " + service);
10079 if (r != null) {
10080 Intent.FilterComparison filter
10081 = new Intent.FilterComparison(intent);
10082 IntentBindRecord b = r.bindings.get(filter);
10083 if (b != null && !b.received) {
10084 b.binder = service;
10085 b.requested = true;
10086 b.received = true;
10087 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010088 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010089 = r.connections.values().iterator();
10090 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010091 ArrayList<ConnectionRecord> clist = it.next();
10092 for (int i=0; i<clist.size(); i++) {
10093 ConnectionRecord c = clist.get(i);
10094 if (!filter.equals(c.binding.intent.intent)) {
10095 if (DEBUG_SERVICE) Slog.v(
10096 TAG, "Not publishing to: " + c);
10097 if (DEBUG_SERVICE) Slog.v(
10098 TAG, "Bound intent: " + c.binding.intent.intent);
10099 if (DEBUG_SERVICE) Slog.v(
10100 TAG, "Published intent: " + intent);
10101 continue;
10102 }
10103 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
10104 try {
10105 c.conn.connected(r.name, service);
10106 } catch (Exception e) {
10107 Slog.w(TAG, "Failure sending service " + r.name +
10108 " to connection " + c.conn.asBinder() +
10109 " (in " + c.binding.client.processName + ")", e);
10110 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010111 }
10112 }
10113 }
10114 }
10115
10116 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
10117
10118 Binder.restoreCallingIdentity(origId);
10119 }
10120 }
10121 }
10122
10123 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
10124 // Refuse possible leaked file descriptors
10125 if (intent != null && intent.hasFileDescriptors() == true) {
10126 throw new IllegalArgumentException("File descriptors passed in Intent");
10127 }
10128
10129 synchronized(this) {
10130 if (!(token instanceof ServiceRecord)) {
10131 throw new IllegalArgumentException("Invalid service token");
10132 }
10133 ServiceRecord r = (ServiceRecord)token;
10134
10135 final long origId = Binder.clearCallingIdentity();
10136
10137 if (r != null) {
10138 Intent.FilterComparison filter
10139 = new Intent.FilterComparison(intent);
10140 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010141 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010142 + " at " + b + ": apps="
10143 + (b != null ? b.apps.size() : 0));
10144 if (b != null) {
10145 if (b.apps.size() > 0) {
10146 // Applications have already bound since the last
10147 // unbind, so just rebind right here.
10148 requestServiceBindingLocked(r, b, true);
10149 } else {
10150 // Note to tell the service the next time there is
10151 // a new client.
10152 b.doRebind = true;
10153 }
10154 }
10155
10156 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
10157
10158 Binder.restoreCallingIdentity(origId);
10159 }
10160 }
10161 }
10162
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010163 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010164 synchronized(this) {
10165 if (!(token instanceof ServiceRecord)) {
10166 throw new IllegalArgumentException("Invalid service token");
10167 }
10168 ServiceRecord r = (ServiceRecord)token;
10169 boolean inStopping = mStoppingServices.contains(token);
10170 if (r != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010171 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010172 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010173 + " with incorrect token: given " + token
10174 + ", expected " + r);
10175 return;
10176 }
10177
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010178 if (type == 1) {
10179 // This is a call from a service start... take care of
10180 // book-keeping.
10181 r.callStart = true;
10182 switch (res) {
10183 case Service.START_STICKY_COMPATIBILITY:
10184 case Service.START_STICKY: {
10185 // We are done with the associated start arguments.
10186 r.findDeliveredStart(startId, true);
10187 // Don't stop if killed.
10188 r.stopIfKilled = false;
10189 break;
10190 }
10191 case Service.START_NOT_STICKY: {
10192 // We are done with the associated start arguments.
10193 r.findDeliveredStart(startId, true);
10194 if (r.lastStartId == startId) {
10195 // There is no more work, and this service
10196 // doesn't want to hang around if killed.
10197 r.stopIfKilled = true;
10198 }
10199 break;
10200 }
10201 case Service.START_REDELIVER_INTENT: {
10202 // We'll keep this item until they explicitly
10203 // call stop for it, but keep track of the fact
10204 // that it was delivered.
10205 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
10206 if (si != null) {
10207 si.deliveryCount = 0;
10208 si.doneExecutingCount++;
10209 // Don't stop if killed.
10210 r.stopIfKilled = true;
10211 }
10212 break;
10213 }
10214 default:
10215 throw new IllegalArgumentException(
10216 "Unknown service start result: " + res);
10217 }
10218 if (res == Service.START_STICKY_COMPATIBILITY) {
10219 r.callStart = false;
10220 }
10221 }
10222
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010223 final long origId = Binder.clearCallingIdentity();
10224 serviceDoneExecutingLocked(r, inStopping);
10225 Binder.restoreCallingIdentity(origId);
10226 } else {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010227 Slog.w(TAG, "Done executing unknown service from pid "
10228 + Binder.getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010229 }
10230 }
10231 }
10232
10233 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010234 if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
10235 + ": nesting=" + r.executeNesting
10236 + ", inStopping=" + inStopping + ", app=" + r.app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070010237 else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010238 r.executeNesting--;
10239 if (r.executeNesting <= 0 && r.app != null) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010240 if (DEBUG_SERVICE) Slog.v(TAG,
10241 "Nesting at 0 of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010242 r.app.executingServices.remove(r);
10243 if (r.app.executingServices.size() == 0) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010244 if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,
10245 "No more executingServices of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010246 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
10247 }
10248 if (inStopping) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010249 if (DEBUG_SERVICE) Slog.v(TAG,
10250 "doneExecuting remove stopping " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010251 mStoppingServices.remove(r);
Mattias Petersson3996b412010-10-27 09:32:51 +020010252 r.bindings.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010253 }
10254 updateOomAdjLocked(r.app);
10255 }
10256 }
10257
10258 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010259 String anrMessage = null;
10260
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010261 synchronized(this) {
10262 if (proc.executingServices.size() == 0 || proc.thread == null) {
10263 return;
10264 }
10265 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
10266 Iterator<ServiceRecord> it = proc.executingServices.iterator();
10267 ServiceRecord timeout = null;
10268 long nextTime = 0;
10269 while (it.hasNext()) {
10270 ServiceRecord sr = it.next();
10271 if (sr.executingStart < maxTime) {
10272 timeout = sr;
10273 break;
10274 }
10275 if (sr.executingStart > nextTime) {
10276 nextTime = sr.executingStart;
10277 }
10278 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010279 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010280 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010281 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010282 } else {
10283 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
10284 msg.obj = proc;
10285 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
10286 }
10287 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010288
10289 if (anrMessage != null) {
10290 appNotResponding(proc, null, null, anrMessage);
10291 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010292 }
10293
10294 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070010295 // BACKUP AND RESTORE
10296 // =========================================================
10297
10298 // Cause the target app to be launched if necessary and its backup agent
10299 // instantiated. The backup agent will invoke backupAgentCreated() on the
10300 // activity manager to announce its creation.
10301 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010302 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070010303 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
10304
10305 synchronized(this) {
10306 // !!! TODO: currently no check here that we're already bound
10307 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
10308 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
10309 synchronized (stats) {
10310 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
10311 }
10312
Dianne Hackborne7f97212011-02-24 14:40:20 -080010313 // Backup agent is now in use, its package can't be stopped.
10314 try {
10315 AppGlobals.getPackageManager().setPackageStoppedState(
10316 app.packageName, false);
10317 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -080010318 } catch (IllegalArgumentException e) {
10319 Slog.w(TAG, "Failed trying to unstop package "
10320 + app.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -080010321 }
10322
Christopher Tate181fafa2009-05-14 11:12:14 -070010323 BackupRecord r = new BackupRecord(ss, app, backupMode);
10324 ComponentName hostingName = new ComponentName(app.packageName, app.backupAgentName);
10325 // startProcessLocked() returns existing proc's record if it's already running
10326 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010327 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070010328 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010329 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070010330 return false;
10331 }
10332
10333 r.app = proc;
10334 mBackupTarget = r;
10335 mBackupAppName = app.packageName;
10336
Christopher Tate6fa95972009-06-05 18:43:55 -070010337 // Try not to kill the process during backup
10338 updateOomAdjLocked(proc);
10339
Christopher Tate181fafa2009-05-14 11:12:14 -070010340 // If the process is already attached, schedule the creation of the backup agent now.
10341 // If it is not yet live, this will be done when it attaches to the framework.
10342 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010343 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070010344 try {
10345 proc.thread.scheduleCreateBackupAgent(app, backupMode);
10346 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070010347 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070010348 }
10349 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010350 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070010351 }
10352 // Invariants: at this point, the target app process exists and the application
10353 // is either already running or in the process of coming up. mBackupTarget and
10354 // mBackupAppName describe the app, so that when it binds back to the AM we
10355 // know that it's scheduled for a backup-agent operation.
10356 }
10357
10358 return true;
10359 }
10360
10361 // A backup agent has just come up
10362 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010363 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070010364 + " = " + agent);
10365
10366 synchronized(this) {
10367 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010368 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070010369 return;
10370 }
Dianne Hackborn06740692010-09-22 22:46:21 -070010371 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010372
Dianne Hackborn06740692010-09-22 22:46:21 -070010373 long oldIdent = Binder.clearCallingIdentity();
10374 try {
10375 IBackupManager bm = IBackupManager.Stub.asInterface(
10376 ServiceManager.getService(Context.BACKUP_SERVICE));
10377 bm.agentConnected(agentPackageName, agent);
10378 } catch (RemoteException e) {
10379 // can't happen; the backup manager service is local
10380 } catch (Exception e) {
10381 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
10382 e.printStackTrace();
10383 } finally {
10384 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070010385 }
10386 }
10387
10388 // done with this agent
10389 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010390 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070010391 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010392 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070010393 return;
10394 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010395
10396 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070010397 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010398 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070010399 return;
10400 }
10401
Christopher Tate181fafa2009-05-14 11:12:14 -070010402 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010403 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070010404 return;
10405 }
10406
Christopher Tate6fa95972009-06-05 18:43:55 -070010407 ProcessRecord proc = mBackupTarget.app;
10408 mBackupTarget = null;
10409 mBackupAppName = null;
10410
10411 // Not backing this app up any more; reset its OOM adjustment
10412 updateOomAdjLocked(proc);
10413
Christopher Tatec7b31e32009-06-10 15:49:30 -070010414 // If the app crashed during backup, 'thread' will be null here
10415 if (proc.thread != null) {
10416 try {
10417 proc.thread.scheduleDestroyBackupAgent(appInfo);
10418 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010419 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070010420 e.printStackTrace();
10421 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010422 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010423 }
10424 }
10425 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010426 // BROADCASTS
10427 // =========================================================
10428
Josh Bartel7f208742010-02-25 11:01:44 -060010429 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010430 List cur) {
10431 final ContentResolver resolver = mContext.getContentResolver();
10432 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
10433 if (list == null) {
10434 return cur;
10435 }
10436 int N = list.size();
10437 for (int i=0; i<N; i++) {
10438 Intent intent = list.get(i);
10439 if (filter.match(resolver, intent, true, TAG) >= 0) {
10440 if (cur == null) {
10441 cur = new ArrayList<Intent>();
10442 }
10443 cur.add(intent);
10444 }
10445 }
10446 return cur;
10447 }
10448
10449 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010450 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010451 + mBroadcastsScheduled);
10452
10453 if (mBroadcastsScheduled) {
10454 return;
10455 }
10456 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
10457 mBroadcastsScheduled = true;
10458 }
10459
10460 public Intent registerReceiver(IApplicationThread caller,
10461 IIntentReceiver receiver, IntentFilter filter, String permission) {
10462 synchronized(this) {
10463 ProcessRecord callerApp = null;
10464 if (caller != null) {
10465 callerApp = getRecordForAppLocked(caller);
10466 if (callerApp == null) {
10467 throw new SecurityException(
10468 "Unable to find app for caller " + caller
10469 + " (pid=" + Binder.getCallingPid()
10470 + ") when registering receiver " + receiver);
10471 }
10472 }
10473
10474 List allSticky = null;
10475
10476 // Look for any matching sticky broadcasts...
10477 Iterator actions = filter.actionsIterator();
10478 if (actions != null) {
10479 while (actions.hasNext()) {
10480 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -060010481 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010482 }
10483 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060010484 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010485 }
10486
10487 // The first sticky in the list is returned directly back to
10488 // the client.
10489 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
10490
Joe Onorato8a9b2202010-02-26 18:56:32 -080010491 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010492 + ": " + sticky);
10493
10494 if (receiver == null) {
10495 return sticky;
10496 }
10497
10498 ReceiverList rl
10499 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10500 if (rl == null) {
10501 rl = new ReceiverList(this, callerApp,
10502 Binder.getCallingPid(),
10503 Binder.getCallingUid(), receiver);
10504 if (rl.app != null) {
10505 rl.app.receivers.add(rl);
10506 } else {
10507 try {
10508 receiver.asBinder().linkToDeath(rl, 0);
10509 } catch (RemoteException e) {
10510 return sticky;
10511 }
10512 rl.linkedToDeath = true;
10513 }
10514 mRegisteredReceivers.put(receiver.asBinder(), rl);
10515 }
10516 BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
10517 rl.add(bf);
10518 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010519 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010520 }
10521 mReceiverResolver.addFilter(bf);
10522
10523 // Enqueue broadcasts for all existing stickies that match
10524 // this filter.
10525 if (allSticky != null) {
10526 ArrayList receivers = new ArrayList();
10527 receivers.add(bf);
10528
10529 int N = allSticky.size();
10530 for (int i=0; i<N; i++) {
10531 Intent intent = (Intent)allSticky.get(i);
10532 BroadcastRecord r = new BroadcastRecord(intent, null,
10533 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010534 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010535 if (mParallelBroadcasts.size() == 0) {
10536 scheduleBroadcastsLocked();
10537 }
10538 mParallelBroadcasts.add(r);
10539 }
10540 }
10541
10542 return sticky;
10543 }
10544 }
10545
10546 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010547 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010548
10549 boolean doNext = false;
10550
10551 synchronized(this) {
10552 ReceiverList rl
10553 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10554 if (rl != null) {
10555 if (rl.curBroadcast != null) {
10556 BroadcastRecord r = rl.curBroadcast;
10557 doNext = finishReceiverLocked(
10558 receiver.asBinder(), r.resultCode, r.resultData,
10559 r.resultExtras, r.resultAbort, true);
10560 }
10561
10562 if (rl.app != null) {
10563 rl.app.receivers.remove(rl);
10564 }
10565 removeReceiverLocked(rl);
10566 if (rl.linkedToDeath) {
10567 rl.linkedToDeath = false;
10568 rl.receiver.asBinder().unlinkToDeath(rl, 0);
10569 }
10570 }
10571 }
10572
10573 if (!doNext) {
10574 return;
10575 }
10576
10577 final long origId = Binder.clearCallingIdentity();
10578 processNextBroadcast(false);
10579 trimApplications();
10580 Binder.restoreCallingIdentity(origId);
10581 }
10582
10583 void removeReceiverLocked(ReceiverList rl) {
10584 mRegisteredReceivers.remove(rl.receiver.asBinder());
10585 int N = rl.size();
10586 for (int i=0; i<N; i++) {
10587 mReceiverResolver.removeFilter(rl.get(i));
10588 }
10589 }
10590
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010591 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
10592 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
10593 ProcessRecord r = mLruProcesses.get(i);
10594 if (r.thread != null) {
10595 try {
10596 r.thread.dispatchPackageBroadcast(cmd, packages);
10597 } catch (RemoteException ex) {
10598 }
10599 }
10600 }
10601 }
10602
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010603 private final int broadcastIntentLocked(ProcessRecord callerApp,
10604 String callerPackage, Intent intent, String resolvedType,
10605 IIntentReceiver resultTo, int resultCode, String resultData,
10606 Bundle map, String requiredPermission,
10607 boolean ordered, boolean sticky, int callingPid, int callingUid) {
10608 intent = new Intent(intent);
10609
Dianne Hackborne7f97212011-02-24 14:40:20 -080010610 // By default broadcasts do not go to stopped apps.
10611 intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
10612
Joe Onorato8a9b2202010-02-26 18:56:32 -080010613 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010614 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
10615 + " ordered=" + ordered);
10616 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010617 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010618 }
10619
10620 // Handle special intents: if this broadcast is from the package
10621 // manager about a package being removed, we need to remove all of
10622 // its activities from the history stack.
10623 final boolean uidRemoved = intent.ACTION_UID_REMOVED.equals(
10624 intent.getAction());
10625 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
10626 || intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010627 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010628 || uidRemoved) {
10629 if (checkComponentPermission(
10630 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080010631 callingPid, callingUid, -1, true)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010632 == PackageManager.PERMISSION_GRANTED) {
10633 if (uidRemoved) {
10634 final Bundle intentExtras = intent.getExtras();
10635 final int uid = intentExtras != null
10636 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
10637 if (uid >= 0) {
10638 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
10639 synchronized (bs) {
10640 bs.removeUidStatsLocked(uid);
10641 }
10642 }
10643 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010644 // If resources are unvailble just force stop all
10645 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010646 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010647 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
10648 if (list != null && (list.length > 0)) {
10649 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010650 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010651 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010652 sendPackageBroadcastLocked(
10653 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010654 }
10655 } else {
10656 Uri data = intent.getData();
10657 String ssp;
10658 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
10659 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
10660 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080010661 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070010662 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070010663 if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
10664 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
10665 new String[] {ssp});
10666 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010667 }
10668 }
10669 }
10670 } else {
10671 String msg = "Permission Denial: " + intent.getAction()
10672 + " broadcast from " + callerPackage + " (pid=" + callingPid
10673 + ", uid=" + callingUid + ")"
10674 + " requires "
10675 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010676 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010677 throw new SecurityException(msg);
10678 }
10679 }
10680
10681 /*
10682 * If this is the time zone changed action, queue up a message that will reset the timezone
10683 * of all currently running processes. This message will get queued up before the broadcast
10684 * happens.
10685 */
10686 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
10687 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
10688 }
10689
Robert Greenwalt03595d02010-11-02 14:08:23 -070010690 if (intent.ACTION_CLEAR_DNS_CACHE.equals(intent.getAction())) {
10691 mHandler.sendEmptyMessage(CLEAR_DNS_CACHE);
10692 }
10693
Robert Greenwalt434203a2010-10-11 16:00:27 -070010694 if (Proxy.PROXY_CHANGE_ACTION.equals(intent.getAction())) {
10695 ProxyProperties proxy = intent.getParcelableExtra("proxy");
10696 mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY, proxy));
10697 }
10698
Dianne Hackborn854060af2009-07-09 18:14:31 -070010699 /*
10700 * Prevent non-system code (defined here to be non-persistent
10701 * processes) from sending protected broadcasts.
10702 */
10703 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
10704 || callingUid == Process.SHELL_UID || callingUid == 0) {
10705 // Always okay.
10706 } else if (callerApp == null || !callerApp.persistent) {
10707 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010708 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -070010709 intent.getAction())) {
10710 String msg = "Permission Denial: not allowed to send broadcast "
10711 + intent.getAction() + " from pid="
10712 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010713 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070010714 throw new SecurityException(msg);
10715 }
10716 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010717 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070010718 return BROADCAST_SUCCESS;
10719 }
10720 }
10721
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010722 // Add to the sticky list if requested.
10723 if (sticky) {
10724 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
10725 callingPid, callingUid)
10726 != PackageManager.PERMISSION_GRANTED) {
10727 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
10728 + callingPid + ", uid=" + callingUid
10729 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010730 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010731 throw new SecurityException(msg);
10732 }
10733 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010734 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010735 + " and enforce permission " + requiredPermission);
10736 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
10737 }
10738 if (intent.getComponent() != null) {
10739 throw new SecurityException(
10740 "Sticky broadcasts can't target a specific component");
10741 }
10742 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
10743 if (list == null) {
10744 list = new ArrayList<Intent>();
10745 mStickyBroadcasts.put(intent.getAction(), list);
10746 }
10747 int N = list.size();
10748 int i;
10749 for (i=0; i<N; i++) {
10750 if (intent.filterEquals(list.get(i))) {
10751 // This sticky already exists, replace it.
10752 list.set(i, new Intent(intent));
10753 break;
10754 }
10755 }
10756 if (i >= N) {
10757 list.add(new Intent(intent));
10758 }
10759 }
10760
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010761 // Figure out who all will receive this broadcast.
10762 List receivers = null;
10763 List<BroadcastFilter> registeredReceivers = null;
10764 try {
10765 if (intent.getComponent() != null) {
10766 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010767 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070010768 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010769 if (ai != null) {
10770 receivers = new ArrayList();
10771 ResolveInfo ri = new ResolveInfo();
10772 ri.activityInfo = ai;
10773 receivers.add(ri);
10774 }
10775 } else {
10776 // Need to resolve the intent to interested receivers...
10777 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
10778 == 0) {
10779 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010780 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010781 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010782 }
Mihai Preda074edef2009-05-18 17:13:31 +020010783 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010784 }
10785 } catch (RemoteException ex) {
10786 // pm is in same process, this will never happen.
10787 }
10788
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010789 final boolean replacePending =
10790 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
10791
Joe Onorato8a9b2202010-02-26 18:56:32 -080010792 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010793 + " replacePending=" + replacePending);
10794
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010795 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
10796 if (!ordered && NR > 0) {
10797 // If we are not serializing this broadcast, then send the
10798 // registered receivers separately so they don't wait for the
10799 // components to be launched.
10800 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10801 callerPackage, callingPid, callingUid, requiredPermission,
10802 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010803 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010804 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010805 TAG, "Enqueueing parallel broadcast " + r
10806 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010807 boolean replaced = false;
10808 if (replacePending) {
10809 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
10810 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010811 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010812 "***** DROPPING PARALLEL: " + intent);
10813 mParallelBroadcasts.set(i, r);
10814 replaced = true;
10815 break;
10816 }
10817 }
10818 }
10819 if (!replaced) {
10820 mParallelBroadcasts.add(r);
10821 scheduleBroadcastsLocked();
10822 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010823 registeredReceivers = null;
10824 NR = 0;
10825 }
10826
10827 // Merge into one list.
10828 int ir = 0;
10829 if (receivers != null) {
10830 // A special case for PACKAGE_ADDED: do not allow the package
10831 // being added to see this broadcast. This prevents them from
10832 // using this as a back door to get run as soon as they are
10833 // installed. Maybe in the future we want to have a special install
10834 // broadcast or such for apps, but we'd like to deliberately make
10835 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010836 String skipPackages[] = null;
10837 if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
10838 || intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
10839 || intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
10840 Uri data = intent.getData();
10841 if (data != null) {
10842 String pkgName = data.getSchemeSpecificPart();
10843 if (pkgName != null) {
10844 skipPackages = new String[] { pkgName };
10845 }
10846 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010847 } else if (intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010848 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070010849 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010850 if (skipPackages != null && (skipPackages.length > 0)) {
10851 for (String skipPackage : skipPackages) {
10852 if (skipPackage != null) {
10853 int NT = receivers.size();
10854 for (int it=0; it<NT; it++) {
10855 ResolveInfo curt = (ResolveInfo)receivers.get(it);
10856 if (curt.activityInfo.packageName.equals(skipPackage)) {
10857 receivers.remove(it);
10858 it--;
10859 NT--;
10860 }
10861 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010862 }
10863 }
10864 }
10865
10866 int NT = receivers != null ? receivers.size() : 0;
10867 int it = 0;
10868 ResolveInfo curt = null;
10869 BroadcastFilter curr = null;
10870 while (it < NT && ir < NR) {
10871 if (curt == null) {
10872 curt = (ResolveInfo)receivers.get(it);
10873 }
10874 if (curr == null) {
10875 curr = registeredReceivers.get(ir);
10876 }
10877 if (curr.getPriority() >= curt.priority) {
10878 // Insert this broadcast record into the final list.
10879 receivers.add(it, curr);
10880 ir++;
10881 curr = null;
10882 it++;
10883 NT++;
10884 } else {
10885 // Skip to the next ResolveInfo in the final list.
10886 it++;
10887 curt = null;
10888 }
10889 }
10890 }
10891 while (ir < NR) {
10892 if (receivers == null) {
10893 receivers = new ArrayList();
10894 }
10895 receivers.add(registeredReceivers.get(ir));
10896 ir++;
10897 }
10898
10899 if ((receivers != null && receivers.size() > 0)
10900 || resultTo != null) {
10901 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
10902 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080010903 receivers, resultTo, resultCode, resultData, map, ordered,
10904 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010905 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010906 TAG, "Enqueueing ordered broadcast " + r
10907 + ": prev had " + mOrderedBroadcasts.size());
10908 if (DEBUG_BROADCAST) {
10909 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010910 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010911 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010912 boolean replaced = false;
10913 if (replacePending) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010914 for (int i=mOrderedBroadcasts.size()-1; i>0; i--) {
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010915 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010916 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080010917 "***** DROPPING ORDERED: " + intent);
10918 mOrderedBroadcasts.set(i, r);
10919 replaced = true;
10920 break;
10921 }
10922 }
10923 }
10924 if (!replaced) {
10925 mOrderedBroadcasts.add(r);
10926 scheduleBroadcastsLocked();
10927 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010928 }
10929
10930 return BROADCAST_SUCCESS;
10931 }
10932
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010933 final Intent verifyBroadcastLocked(Intent intent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010934 // Refuse possible leaked file descriptors
10935 if (intent != null && intent.hasFileDescriptors() == true) {
10936 throw new IllegalArgumentException("File descriptors passed in Intent");
10937 }
10938
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010939 int flags = intent.getFlags();
10940
10941 if (!mProcessesReady) {
10942 // if the caller really truly claims to know what they're doing, go
10943 // ahead and allow the broadcast without launching any receivers
10944 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
10945 intent = new Intent(intent);
10946 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
10947 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
10948 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
10949 + " before boot completion");
10950 throw new IllegalStateException("Cannot broadcast before boot completed");
10951 }
10952 }
10953
10954 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
10955 throw new IllegalArgumentException(
10956 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
10957 }
10958
10959 return intent;
10960 }
10961
10962 public final int broadcastIntent(IApplicationThread caller,
10963 Intent intent, String resolvedType, IIntentReceiver resultTo,
10964 int resultCode, String resultData, Bundle map,
10965 String requiredPermission, boolean serialized, boolean sticky) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010966 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010967 intent = verifyBroadcastLocked(intent);
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010968
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010969 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10970 final int callingPid = Binder.getCallingPid();
10971 final int callingUid = Binder.getCallingUid();
10972 final long origId = Binder.clearCallingIdentity();
10973 int res = broadcastIntentLocked(callerApp,
10974 callerApp != null ? callerApp.info.packageName : null,
10975 intent, resolvedType, resultTo,
10976 resultCode, resultData, map, requiredPermission, serialized,
10977 sticky, callingPid, callingUid);
10978 Binder.restoreCallingIdentity(origId);
10979 return res;
10980 }
10981 }
10982
10983 int broadcastIntentInPackage(String packageName, int uid,
10984 Intent intent, String resolvedType, IIntentReceiver resultTo,
10985 int resultCode, String resultData, Bundle map,
10986 String requiredPermission, boolean serialized, boolean sticky) {
10987 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010988 intent = verifyBroadcastLocked(intent);
10989
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010990 final long origId = Binder.clearCallingIdentity();
10991 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
10992 resultTo, resultCode, resultData, map, requiredPermission,
10993 serialized, sticky, -1, uid);
10994 Binder.restoreCallingIdentity(origId);
10995 return res;
10996 }
10997 }
10998
10999 public final void unbroadcastIntent(IApplicationThread caller,
11000 Intent intent) {
11001 // Refuse possible leaked file descriptors
11002 if (intent != null && intent.hasFileDescriptors() == true) {
11003 throw new IllegalArgumentException("File descriptors passed in Intent");
11004 }
11005
11006 synchronized(this) {
11007 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
11008 != PackageManager.PERMISSION_GRANTED) {
11009 String msg = "Permission Denial: unbroadcastIntent() from pid="
11010 + Binder.getCallingPid()
11011 + ", uid=" + Binder.getCallingUid()
11012 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011013 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011014 throw new SecurityException(msg);
11015 }
11016 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
11017 if (list != null) {
11018 int N = list.size();
11019 int i;
11020 for (i=0; i<N; i++) {
11021 if (intent.filterEquals(list.get(i))) {
11022 list.remove(i);
11023 break;
11024 }
11025 }
11026 }
11027 }
11028 }
11029
11030 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
11031 String resultData, Bundle resultExtras, boolean resultAbort,
11032 boolean explicit) {
11033 if (mOrderedBroadcasts.size() == 0) {
11034 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011035 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011036 }
11037 return false;
11038 }
11039 BroadcastRecord r = mOrderedBroadcasts.get(0);
11040 if (r.receiver == null) {
11041 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011042 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011043 }
11044 return false;
11045 }
11046 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011047 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011048 return false;
11049 }
11050 int state = r.state;
11051 r.state = r.IDLE;
11052 if (state == r.IDLE) {
11053 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011054 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011055 }
11056 }
11057 r.receiver = null;
11058 r.intent.setComponent(null);
11059 if (r.curApp != null) {
11060 r.curApp.curReceiver = null;
11061 }
11062 if (r.curFilter != null) {
11063 r.curFilter.receiverList.curBroadcast = null;
11064 }
11065 r.curFilter = null;
11066 r.curApp = null;
11067 r.curComponent = null;
11068 r.curReceiver = null;
11069 mPendingBroadcast = null;
11070
11071 r.resultCode = resultCode;
11072 r.resultData = resultData;
11073 r.resultExtras = resultExtras;
11074 r.resultAbort = resultAbort;
11075
11076 // We will process the next receiver right now if this is finishing
11077 // an app receiver (which is always asynchronous) or after we have
11078 // come back from calling a receiver.
11079 return state == BroadcastRecord.APP_RECEIVE
11080 || state == BroadcastRecord.CALL_DONE_RECEIVE;
11081 }
11082
11083 public void finishReceiver(IBinder who, int resultCode, String resultData,
11084 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011085 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011086
11087 // Refuse possible leaked file descriptors
11088 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
11089 throw new IllegalArgumentException("File descriptors passed in Bundle");
11090 }
11091
11092 boolean doNext;
11093
11094 final long origId = Binder.clearCallingIdentity();
11095
11096 synchronized(this) {
11097 doNext = finishReceiverLocked(
11098 who, resultCode, resultData, resultExtras, resultAbort, true);
11099 }
11100
11101 if (doNext) {
11102 processNextBroadcast(false);
11103 }
11104 trimApplications();
11105
11106 Binder.restoreCallingIdentity(origId);
11107 }
11108
Jeff Brown4d94a762010-09-23 11:33:28 -070011109 private final void logBroadcastReceiverDiscardLocked(BroadcastRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011110 if (r.nextReceiver > 0) {
11111 Object curReceiver = r.receivers.get(r.nextReceiver-1);
11112 if (curReceiver instanceof BroadcastFilter) {
11113 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080011114 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011115 System.identityHashCode(r),
11116 r.intent.getAction(),
11117 r.nextReceiver - 1,
11118 System.identityHashCode(bf));
11119 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080011120 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011121 System.identityHashCode(r),
11122 r.intent.getAction(),
11123 r.nextReceiver - 1,
11124 ((ResolveInfo)curReceiver).toString());
11125 }
11126 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011127 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011128 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011129 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011130 System.identityHashCode(r),
11131 r.intent.getAction(),
11132 r.nextReceiver,
11133 "NONE");
11134 }
11135 }
11136
Jeff Brown4d94a762010-09-23 11:33:28 -070011137 private final void setBroadcastTimeoutLocked(long timeoutTime) {
11138 if (! mPendingBroadcastTimeoutMessage) {
11139 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
11140 mHandler.sendMessageAtTime(msg, timeoutTime);
11141 mPendingBroadcastTimeoutMessage = true;
11142 }
11143 }
11144
11145 private final void cancelBroadcastTimeoutLocked() {
11146 if (mPendingBroadcastTimeoutMessage) {
11147 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
11148 mPendingBroadcastTimeoutMessage = false;
11149 }
11150 }
11151
11152 private final void broadcastTimeoutLocked(boolean fromMsg) {
11153 if (fromMsg) {
11154 mPendingBroadcastTimeoutMessage = false;
11155 }
11156
11157 if (mOrderedBroadcasts.size() == 0) {
11158 return;
11159 }
11160
11161 long now = SystemClock.uptimeMillis();
11162 BroadcastRecord r = mOrderedBroadcasts.get(0);
11163 if (fromMsg) {
11164 if (mDidDexOpt) {
11165 // Delay timeouts until dexopt finishes.
11166 mDidDexOpt = false;
11167 long timeoutTime = SystemClock.uptimeMillis() + BROADCAST_TIMEOUT;
11168 setBroadcastTimeoutLocked(timeoutTime);
11169 return;
11170 }
11171 if (! mProcessesReady) {
11172 // Only process broadcast timeouts if the system is ready. That way
11173 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
11174 // to do heavy lifting for system up.
11175 return;
11176 }
11177
11178 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
11179 if (timeoutTime > now) {
11180 // We can observe premature timeouts because we do not cancel and reset the
11181 // broadcast timeout message after each receiver finishes. Instead, we set up
11182 // an initial timeout then kick it down the road a little further as needed
11183 // when it expires.
11184 if (DEBUG_BROADCAST) Slog.v(TAG,
11185 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
11186 + timeoutTime);
11187 setBroadcastTimeoutLocked(timeoutTime);
11188 return;
11189 }
11190 }
11191
11192 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver
11193 + ", started " + (now - r.receiverTime) + "ms ago");
11194 r.receiverTime = now;
11195 r.anrCount++;
11196
11197 // Current receiver has passed its expiration date.
11198 if (r.nextReceiver <= 0) {
11199 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
11200 return;
11201 }
11202
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011203 ProcessRecord app = null;
11204 String anrMessage = null;
11205
Jeff Brown4d94a762010-09-23 11:33:28 -070011206 Object curReceiver = r.receivers.get(r.nextReceiver-1);
11207 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
11208 logBroadcastReceiverDiscardLocked(r);
11209 if (curReceiver instanceof BroadcastFilter) {
11210 BroadcastFilter bf = (BroadcastFilter)curReceiver;
11211 if (bf.receiverList.pid != 0
11212 && bf.receiverList.pid != MY_PID) {
11213 synchronized (this.mPidsSelfLocked) {
11214 app = this.mPidsSelfLocked.get(
11215 bf.receiverList.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011216 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011217 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011218 } else {
11219 app = r.curApp;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011220 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011221
Jeff Brown4d94a762010-09-23 11:33:28 -070011222 if (app != null) {
11223 anrMessage = "Broadcast of " + r.intent.toString();
11224 }
11225
11226 if (mPendingBroadcast == r) {
11227 mPendingBroadcast = null;
11228 }
11229
11230 // Move on to the next receiver.
11231 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
11232 r.resultExtras, r.resultAbort, true);
11233 scheduleBroadcastsLocked();
11234
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011235 if (anrMessage != null) {
Jeff Brown4d94a762010-09-23 11:33:28 -070011236 // Post the ANR to the handler since we do not want to process ANRs while
11237 // potentially holding our lock.
11238 mHandler.post(new AppNotResponding(app, anrMessage));
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011239 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011240 }
11241
11242 private final void processCurBroadcastLocked(BroadcastRecord r,
11243 ProcessRecord app) throws RemoteException {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011244 if (DEBUG_BROADCAST) Slog.v(TAG,
11245 "Process cur broadcast " + r + " for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011246 if (app.thread == null) {
11247 throw new RemoteException();
11248 }
11249 r.receiver = app.thread.asBinder();
11250 r.curApp = app;
11251 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011252 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011253
11254 // Tell the application to launch this receiver.
11255 r.intent.setComponent(r.curComponent);
11256
11257 boolean started = false;
11258 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011259 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011260 "Delivering to component " + r.curComponent
11261 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070011262 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011263 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
11264 r.resultCode, r.resultData, r.resultExtras, r.ordered);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011265 if (DEBUG_BROADCAST) Slog.v(TAG,
11266 "Process cur broadcast " + r + " DELIVERED for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011267 started = true;
11268 } finally {
11269 if (!started) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011270 if (DEBUG_BROADCAST) Slog.v(TAG,
11271 "Process cur broadcast " + r + ": NOT STARTED!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011272 r.receiver = null;
11273 r.curApp = null;
11274 app.curReceiver = null;
11275 }
11276 }
11277
11278 }
11279
Jeff Brown4d94a762010-09-23 11:33:28 -070011280 static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011281 Intent intent, int resultCode, String data, Bundle extras,
11282 boolean ordered, boolean sticky) throws RemoteException {
Jeff Brown4d94a762010-09-23 11:33:28 -070011283 // Send the intent to the receiver asynchronously using one-way binder calls.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011284 if (app != null && app.thread != null) {
11285 // If we have an app thread, do the call through that so it is
11286 // correctly ordered with other one-way calls.
11287 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011288 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011289 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011290 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011291 }
11292 }
11293
Jeff Brown4d94a762010-09-23 11:33:28 -070011294 private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011295 BroadcastFilter filter, boolean ordered) {
11296 boolean skip = false;
11297 if (filter.requiredPermission != null) {
11298 int perm = checkComponentPermission(filter.requiredPermission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011299 r.callingPid, r.callingUid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011300 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011301 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011302 + r.intent.toString()
11303 + " from " + r.callerPackage + " (pid="
11304 + r.callingPid + ", uid=" + r.callingUid + ")"
11305 + " requires " + filter.requiredPermission
11306 + " due to registered receiver " + filter);
11307 skip = true;
11308 }
11309 }
11310 if (r.requiredPermission != null) {
11311 int perm = checkComponentPermission(r.requiredPermission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011312 filter.receiverList.pid, filter.receiverList.uid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011313 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011314 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011315 + r.intent.toString()
11316 + " to " + filter.receiverList.app
11317 + " (pid=" + filter.receiverList.pid
11318 + ", uid=" + filter.receiverList.uid + ")"
11319 + " requires " + r.requiredPermission
11320 + " due to sender " + r.callerPackage
11321 + " (uid " + r.callingUid + ")");
11322 skip = true;
11323 }
11324 }
11325
11326 if (!skip) {
11327 // If this is not being sent as an ordered broadcast, then we
11328 // don't want to touch the fields that keep track of the current
11329 // state of ordered broadcasts.
11330 if (ordered) {
11331 r.receiver = filter.receiverList.receiver.asBinder();
11332 r.curFilter = filter;
11333 filter.receiverList.curBroadcast = r;
11334 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011335 if (filter.receiverList.app != null) {
11336 // Bump hosting application to no longer be in background
11337 // scheduling class. Note that we can't do that if there
11338 // isn't an app... but we can only be in that case for
11339 // things that directly call the IActivityManager API, which
11340 // are already core system stuff so don't matter for this.
11341 r.curApp = filter.receiverList.app;
11342 filter.receiverList.app.curReceiver = r;
11343 updateOomAdjLocked();
11344 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011345 }
11346 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011347 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011348 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011349 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011350 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011351 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011352 performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011353 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011354 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011355 if (ordered) {
11356 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
11357 }
11358 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011359 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011360 if (ordered) {
11361 r.receiver = null;
11362 r.curFilter = null;
11363 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011364 if (filter.receiverList.app != null) {
11365 filter.receiverList.app.curReceiver = null;
11366 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011367 }
11368 }
11369 }
11370 }
11371
Dianne Hackborn12527f92009-11-11 17:39:50 -080011372 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
11373 if (r.callingUid < 0) {
11374 // This was from a registerReceiver() call; ignore it.
11375 return;
11376 }
11377 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
11378 MAX_BROADCAST_HISTORY-1);
11379 r.finishTime = SystemClock.uptimeMillis();
11380 mBroadcastHistory[0] = r;
11381 }
11382
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011383 private final void processNextBroadcast(boolean fromMsg) {
11384 synchronized(this) {
11385 BroadcastRecord r;
11386
Joe Onorato8a9b2202010-02-26 18:56:32 -080011387 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011388 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011389 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011390
11391 updateCpuStats();
11392
11393 if (fromMsg) {
11394 mBroadcastsScheduled = false;
11395 }
11396
11397 // First, deliver any non-serialized broadcasts right away.
11398 while (mParallelBroadcasts.size() > 0) {
11399 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080011400 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011401 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011402 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011403 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011404 for (int i=0; i<N; i++) {
11405 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011406 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011407 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011408 + target + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011409 deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011410 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080011411 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011412 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011413 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011414 }
11415
11416 // Now take care of the next serialized one...
11417
11418 // If we are waiting for a process to come up to handle the next
11419 // broadcast, then do nothing at this point. Just in case, we
11420 // check that the process we're waiting for still exists.
11421 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070011422 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011423 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070011424 + mPendingBroadcast.curApp);
11425 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011426
11427 boolean isDead;
11428 synchronized (mPidsSelfLocked) {
11429 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
11430 }
11431 if (!isDead) {
11432 // It's still alive, so keep waiting
11433 return;
11434 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011435 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011436 + " died before responding to broadcast");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011437 mPendingBroadcast.state = BroadcastRecord.IDLE;
11438 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011439 mPendingBroadcast = null;
11440 }
11441 }
11442
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011443 boolean looped = false;
11444
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011445 do {
11446 if (mOrderedBroadcasts.size() == 0) {
11447 // No more broadcasts pending, so all done!
11448 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011449 if (looped) {
11450 // If we had finished the last ordered broadcast, then
11451 // make sure all processes have correct oom and sched
11452 // adjustments.
11453 updateOomAdjLocked();
11454 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011455 return;
11456 }
11457 r = mOrderedBroadcasts.get(0);
11458 boolean forceReceive = false;
11459
11460 // Ensure that even if something goes awry with the timeout
11461 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011462 // and continue to make progress.
11463 //
11464 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
Jeff Brown4d94a762010-09-23 11:33:28 -070011465 // receivers don't get executed with timeouts. They're intended for
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011466 // one time heavy lifting after system upgrades and can take
11467 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011468 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011469 if (mProcessesReady && r.dispatchTime > 0) {
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011470 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011471 if ((numReceivers > 0) &&
11472 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011473 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011474 + " now=" + now
11475 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080011476 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011477 + " intent=" + r.intent
11478 + " numReceivers=" + numReceivers
11479 + " nextReceiver=" + r.nextReceiver
11480 + " state=" + r.state);
Jeff Brown4d94a762010-09-23 11:33:28 -070011481 broadcastTimeoutLocked(false); // forcibly finish this broadcast
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011482 forceReceive = true;
11483 r.state = BroadcastRecord.IDLE;
11484 }
11485 }
11486
11487 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011488 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011489 "processNextBroadcast() called when not idle (state="
11490 + r.state + ")");
11491 return;
11492 }
11493
11494 if (r.receivers == null || r.nextReceiver >= numReceivers
11495 || r.resultAbort || forceReceive) {
11496 // No more receivers for this broadcast! Send the final
11497 // result if requested...
11498 if (r.resultTo != null) {
11499 try {
11500 if (DEBUG_BROADCAST) {
11501 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011502 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011503 + " seq=" + seq + " app=" + r.callerApp);
11504 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011505 performReceiveLocked(r.callerApp, r.resultTo,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011506 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011507 r.resultData, r.resultExtras, false, false);
Johannes Carlssonb5a86542010-10-27 10:08:10 +020011508 // Set this to null so that the reference
11509 // (local and remote) isnt kept in the mBroadcastHistory.
11510 r.resultTo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011511 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011512 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011513 }
11514 }
11515
Joe Onorato8a9b2202010-02-26 18:56:32 -080011516 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
Jeff Brown4d94a762010-09-23 11:33:28 -070011517 cancelBroadcastTimeoutLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011518
Joe Onorato8a9b2202010-02-26 18:56:32 -080011519 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011520 + r);
11521
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011522 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080011523 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011524 mOrderedBroadcasts.remove(0);
11525 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011526 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011527 continue;
11528 }
11529 } while (r == null);
11530
11531 // Get the next receiver...
11532 int recIdx = r.nextReceiver++;
11533
11534 // Keep track of when this receiver started, and make sure there
11535 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080011536 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011537 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080011538 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011539
Joe Onorato8a9b2202010-02-26 18:56:32 -080011540 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011541 + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011542 }
11543 if (! mPendingBroadcastTimeoutMessage) {
11544 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011545 if (DEBUG_BROADCAST) Slog.v(TAG,
Jeff Brown4d94a762010-09-23 11:33:28 -070011546 "Submitting BROADCAST_TIMEOUT_MSG for " + r + " at " + timeoutTime);
11547 setBroadcastTimeoutLocked(timeoutTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011548 }
11549
11550 Object nextReceiver = r.receivers.get(recIdx);
11551 if (nextReceiver instanceof BroadcastFilter) {
11552 // Simple case: this is a registered receiver who gets
11553 // a direct call.
11554 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011555 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011556 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011557 + filter + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011558 deliverToRegisteredReceiverLocked(r, filter, r.ordered);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011559 if (r.receiver == null || !r.ordered) {
11560 // The receiver has already finished, so schedule to
11561 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011562 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
11563 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011564 r.state = BroadcastRecord.IDLE;
11565 scheduleBroadcastsLocked();
11566 }
11567 return;
11568 }
11569
11570 // Hard case: need to instantiate the receiver, possibly
11571 // starting its application process to host it.
11572
11573 ResolveInfo info =
11574 (ResolveInfo)nextReceiver;
11575
11576 boolean skip = false;
11577 int perm = checkComponentPermission(info.activityInfo.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011578 r.callingPid, r.callingUid, info.activityInfo.applicationInfo.uid,
11579 info.activityInfo.exported);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011580 if (perm != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011581 if (!info.activityInfo.exported) {
11582 Slog.w(TAG, "Permission Denial: broadcasting "
11583 + r.intent.toString()
11584 + " from " + r.callerPackage + " (pid=" + r.callingPid
11585 + ", uid=" + r.callingUid + ")"
11586 + " is not exported from uid " + info.activityInfo.applicationInfo.uid
11587 + " due to receiver " + info.activityInfo.packageName
11588 + "/" + info.activityInfo.name);
11589 } else {
11590 Slog.w(TAG, "Permission Denial: broadcasting "
11591 + r.intent.toString()
11592 + " from " + r.callerPackage + " (pid=" + r.callingPid
11593 + ", uid=" + r.callingUid + ")"
11594 + " requires " + info.activityInfo.permission
11595 + " due to receiver " + info.activityInfo.packageName
11596 + "/" + info.activityInfo.name);
11597 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011598 skip = true;
11599 }
11600 if (r.callingUid != Process.SYSTEM_UID &&
11601 r.requiredPermission != null) {
11602 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011603 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011604 checkPermission(r.requiredPermission,
11605 info.activityInfo.applicationInfo.packageName);
11606 } catch (RemoteException e) {
11607 perm = PackageManager.PERMISSION_DENIED;
11608 }
11609 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011610 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011611 + r.intent + " to "
11612 + info.activityInfo.applicationInfo.packageName
11613 + " requires " + r.requiredPermission
11614 + " due to sender " + r.callerPackage
11615 + " (uid " + r.callingUid + ")");
11616 skip = true;
11617 }
11618 }
11619 if (r.curApp != null && r.curApp.crashing) {
11620 // If the target process is crashing, just skip it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011621 if (DEBUG_BROADCAST) Slog.v(TAG,
11622 "Skipping deliver ordered " + r + " to " + r.curApp
11623 + ": process crashing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011624 skip = true;
11625 }
11626
11627 if (skip) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011628 if (DEBUG_BROADCAST) Slog.v(TAG,
11629 "Skipping delivery of ordered " + r + " for whatever reason");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011630 r.receiver = null;
11631 r.curFilter = null;
11632 r.state = BroadcastRecord.IDLE;
11633 scheduleBroadcastsLocked();
11634 return;
11635 }
11636
11637 r.state = BroadcastRecord.APP_RECEIVE;
11638 String targetProcess = info.activityInfo.processName;
11639 r.curComponent = new ComponentName(
11640 info.activityInfo.applicationInfo.packageName,
11641 info.activityInfo.name);
11642 r.curReceiver = info.activityInfo;
11643
Dianne Hackborne7f97212011-02-24 14:40:20 -080011644 // Broadcast is being executed, its package can't be stopped.
11645 try {
11646 AppGlobals.getPackageManager().setPackageStoppedState(
11647 r.curComponent.getPackageName(), false);
11648 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -080011649 } catch (IllegalArgumentException e) {
11650 Slog.w(TAG, "Failed trying to unstop package "
11651 + r.curComponent.getPackageName() + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -080011652 }
11653
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011654 // Is this receiver's application already running?
11655 ProcessRecord app = getProcessRecordLocked(targetProcess,
11656 info.activityInfo.applicationInfo.uid);
11657 if (app != null && app.thread != null) {
11658 try {
11659 processCurBroadcastLocked(r, app);
11660 return;
11661 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011662 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011663 + r.curComponent, e);
11664 }
11665
11666 // If a dead object exception was thrown -- fall through to
11667 // restart the application.
11668 }
11669
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011670 // Not running -- get it started, to be executed when the app comes up.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011671 if (DEBUG_BROADCAST) Slog.v(TAG,
11672 "Need to start app " + targetProcess + " for broadcast " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011673 if ((r.curApp=startProcessLocked(targetProcess,
11674 info.activityInfo.applicationInfo, true,
11675 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011676 "broadcast", r.curComponent,
11677 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
11678 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011679 // Ah, this recipient is unavailable. Finish it if necessary,
11680 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011681 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011682 + info.activityInfo.applicationInfo.packageName + "/"
11683 + info.activityInfo.applicationInfo.uid + " for broadcast "
11684 + r.intent + ": process is bad");
Jeff Brown4d94a762010-09-23 11:33:28 -070011685 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011686 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
11687 r.resultExtras, r.resultAbort, true);
11688 scheduleBroadcastsLocked();
11689 r.state = BroadcastRecord.IDLE;
11690 return;
11691 }
11692
11693 mPendingBroadcast = r;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011694 mPendingBroadcastRecvIndex = recIdx;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011695 }
11696 }
11697
11698 // =========================================================
11699 // INSTRUMENTATION
11700 // =========================================================
11701
11702 public boolean startInstrumentation(ComponentName className,
11703 String profileFile, int flags, Bundle arguments,
11704 IInstrumentationWatcher watcher) {
11705 // Refuse possible leaked file descriptors
11706 if (arguments != null && arguments.hasFileDescriptors()) {
11707 throw new IllegalArgumentException("File descriptors passed in Bundle");
11708 }
11709
11710 synchronized(this) {
11711 InstrumentationInfo ii = null;
11712 ApplicationInfo ai = null;
11713 try {
11714 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011715 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011716 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011717 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011718 } catch (PackageManager.NameNotFoundException e) {
11719 }
11720 if (ii == null) {
11721 reportStartInstrumentationFailure(watcher, className,
11722 "Unable to find instrumentation info for: " + className);
11723 return false;
11724 }
11725 if (ai == null) {
11726 reportStartInstrumentationFailure(watcher, className,
11727 "Unable to find instrumentation target package: " + ii.targetPackage);
11728 return false;
11729 }
11730
11731 int match = mContext.getPackageManager().checkSignatures(
11732 ii.targetPackage, ii.packageName);
11733 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
11734 String msg = "Permission Denial: starting instrumentation "
11735 + className + " from pid="
11736 + Binder.getCallingPid()
11737 + ", uid=" + Binder.getCallingPid()
11738 + " not allowed because package " + ii.packageName
11739 + " does not have a signature matching the target "
11740 + ii.targetPackage;
11741 reportStartInstrumentationFailure(watcher, className, msg);
11742 throw new SecurityException(msg);
11743 }
11744
11745 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011746 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011747 ProcessRecord app = addAppLocked(ai);
11748 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070011749 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011750 app.instrumentationProfileFile = profileFile;
11751 app.instrumentationArguments = arguments;
11752 app.instrumentationWatcher = watcher;
11753 app.instrumentationResultClass = className;
11754 Binder.restoreCallingIdentity(origId);
11755 }
11756
11757 return true;
11758 }
11759
11760 /**
11761 * Report errors that occur while attempting to start Instrumentation. Always writes the
11762 * error to the logs, but if somebody is watching, send the report there too. This enables
11763 * the "am" command to report errors with more information.
11764 *
11765 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
11766 * @param cn The component name of the instrumentation.
11767 * @param report The error report.
11768 */
11769 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
11770 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011771 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011772 try {
11773 if (watcher != null) {
11774 Bundle results = new Bundle();
11775 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
11776 results.putString("Error", report);
11777 watcher.instrumentationStatus(cn, -1, results);
11778 }
11779 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011780 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011781 }
11782 }
11783
11784 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
11785 if (app.instrumentationWatcher != null) {
11786 try {
11787 // NOTE: IInstrumentationWatcher *must* be oneway here
11788 app.instrumentationWatcher.instrumentationFinished(
11789 app.instrumentationClass,
11790 resultCode,
11791 results);
11792 } catch (RemoteException e) {
11793 }
11794 }
11795 app.instrumentationWatcher = null;
11796 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070011797 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011798 app.instrumentationProfileFile = null;
11799 app.instrumentationArguments = null;
11800
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011801 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011802 }
11803
11804 public void finishInstrumentation(IApplicationThread target,
11805 int resultCode, Bundle results) {
11806 // Refuse possible leaked file descriptors
11807 if (results != null && results.hasFileDescriptors()) {
11808 throw new IllegalArgumentException("File descriptors passed in Intent");
11809 }
11810
11811 synchronized(this) {
11812 ProcessRecord app = getRecordForAppLocked(target);
11813 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011814 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011815 return;
11816 }
11817 final long origId = Binder.clearCallingIdentity();
11818 finishInstrumentationLocked(app, resultCode, results);
11819 Binder.restoreCallingIdentity(origId);
11820 }
11821 }
11822
11823 // =========================================================
11824 // CONFIGURATION
11825 // =========================================================
11826
11827 public ConfigurationInfo getDeviceConfigurationInfo() {
11828 ConfigurationInfo config = new ConfigurationInfo();
11829 synchronized (this) {
11830 config.reqTouchScreen = mConfiguration.touchscreen;
11831 config.reqKeyboardType = mConfiguration.keyboard;
11832 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070011833 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
11834 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011835 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
11836 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070011837 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
11838 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011839 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
11840 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070011841 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011842 }
11843 return config;
11844 }
11845
11846 public Configuration getConfiguration() {
11847 Configuration ci;
11848 synchronized(this) {
11849 ci = new Configuration(mConfiguration);
11850 }
11851 return ci;
11852 }
11853
11854 public void updateConfiguration(Configuration values) {
11855 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
11856 "updateConfiguration()");
11857
11858 synchronized(this) {
11859 if (values == null && mWindowManager != null) {
11860 // sentinel: fetch the current configuration from the window manager
11861 values = mWindowManager.computeNewConfiguration();
11862 }
11863
11864 final long origId = Binder.clearCallingIdentity();
11865 updateConfigurationLocked(values, null);
11866 Binder.restoreCallingIdentity(origId);
11867 }
11868 }
11869
11870 /**
11871 * Do either or both things: (1) change the current configuration, and (2)
11872 * make sure the given activity is running with the (now) current
11873 * configuration. Returns true if the activity has been left running, or
11874 * false if <var>starting</var> is being destroyed to match the new
11875 * configuration.
11876 */
11877 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011878 ActivityRecord starting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011879 int changes = 0;
11880
11881 boolean kept = true;
11882
11883 if (values != null) {
11884 Configuration newConfig = new Configuration(mConfiguration);
11885 changes = newConfig.updateFrom(values);
11886 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011887 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011888 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011889 }
11890
Doug Zongker2bec3d42009-12-04 12:52:44 -080011891 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011892
11893 if (values.locale != null) {
11894 saveLocaleLocked(values.locale,
11895 !values.locale.equals(mConfiguration.locale),
11896 values.userSetLocale);
11897 }
11898
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011899 mConfigurationSeq++;
11900 if (mConfigurationSeq <= 0) {
11901 mConfigurationSeq = 1;
11902 }
11903 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011904 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011905 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080011906
11907 AttributeCache ac = AttributeCache.instance();
11908 if (ac != null) {
11909 ac.updateConfiguration(mConfiguration);
11910 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011911
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080011912 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
11913 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
11914 msg.obj = new Configuration(mConfiguration);
11915 mHandler.sendMessage(msg);
11916 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011917
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011918 for (int i=mLruProcesses.size()-1; i>=0; i--) {
11919 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011920 try {
11921 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011922 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070011923 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011924 app.thread.scheduleConfigurationChanged(mConfiguration);
11925 }
11926 } catch (Exception e) {
11927 }
11928 }
11929 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011930 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
11931 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011932 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
11933 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080011934 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
11935 broadcastIntentLocked(null, null,
11936 new Intent(Intent.ACTION_LOCALE_CHANGED),
11937 null, null, 0, null, null,
11938 null, false, false, MY_PID, Process.SYSTEM_UID);
11939 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011940 }
11941 }
11942
11943 if (changes != 0 && starting == null) {
11944 // If the configuration changed, and the caller is not already
11945 // in the process of starting an activity, then find the top
11946 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011947 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011948 }
11949
11950 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011951 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
Dianne Hackborn5f4d6432010-12-21 20:40:11 -080011952 // And we need to make sure at this point that all other activities
11953 // are made visible with the correct configuration.
11954 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011955 }
11956
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011957 if (values != null && mWindowManager != null) {
11958 mWindowManager.setNewConfiguration(mConfiguration);
11959 }
11960
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011961 return kept;
11962 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011963
11964 /**
11965 * Save the locale. You must be inside a synchronized (this) block.
11966 */
11967 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
11968 if(isDiff) {
11969 SystemProperties.set("user.language", l.getLanguage());
11970 SystemProperties.set("user.region", l.getCountry());
11971 }
11972
11973 if(isPersist) {
11974 SystemProperties.set("persist.sys.language", l.getLanguage());
11975 SystemProperties.set("persist.sys.country", l.getCountry());
11976 SystemProperties.set("persist.sys.localevar", l.getVariant());
11977 }
11978 }
11979
11980 // =========================================================
11981 // LIFETIME MANAGEMENT
11982 // =========================================================
11983
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011984 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
11985 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011986 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011987 // This adjustment has already been computed. If we are calling
11988 // from the top, we may have already computed our adjustment with
11989 // an earlier hidden adjustment that isn't really for us... if
11990 // so, use the new hidden adjustment.
11991 if (!recursed && app.hidden) {
11992 app.curAdj = hiddenAdj;
11993 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011994 return app.curAdj;
11995 }
11996
11997 if (app.thread == null) {
11998 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080011999 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012000 return (app.curAdj=EMPTY_APP_ADJ);
12001 }
12002
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012003 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
12004 // The max adjustment doesn't allow this app to be anything
12005 // below foreground, so it is not worth doing work for it.
12006 app.adjType = "fixed";
12007 app.adjSeq = mAdjSeq;
12008 app.curRawAdj = app.maxAdj;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012009 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012010 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
12011 return (app.curAdj=app.maxAdj);
12012 }
12013
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012014 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012015 app.adjSource = null;
12016 app.adjTarget = null;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012017 app.keeping = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012018 app.empty = false;
12019 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012020
The Android Open Source Project4df24232009-03-05 14:34:35 -080012021 // Determine the importance of the process, starting with most
12022 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012023 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012024 int schedGroup;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012025 int N;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012026 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012027 // The last app on the list is the foreground app.
12028 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012029 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012030 app.adjType = "top-activity";
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012031 } else if (app.instrumentationClass != null) {
12032 // Don't want to kill running instrumentation.
12033 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012034 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012035 app.adjType = "instrumentation";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012036 } else if (app.curReceiver != null ||
12037 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
12038 // An app that is currently receiving a broadcast 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 = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012043 } else if (app.executingServices.size() > 0) {
12044 // An app that is currently executing a service callback also
12045 // counts as being in the foreground.
12046 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012047 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012048 app.adjType = "exec-service";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012049 } else if ((N=app.activities.size()) != 0) {
12050 // This app is in the background with paused activities.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012051 app.hidden = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012052 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012053 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012054 app.adjType = "bg-activities";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012055 N = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012056 for (int j=0; j<N; j++) {
Dianne Hackborn0aae2d42010-12-07 23:51:29 -080012057 ActivityRecord r = app.activities.get(j);
12058 if (r.visible) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012059 // This app has a visible activity!
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012060 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012061 adj = VISIBLE_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012062 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012063 app.adjType = "visible";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012064 break;
Dianne Hackborn0aae2d42010-12-07 23:51:29 -080012065 } else if (r.state == ActivityState.PAUSING
12066 || r.state == ActivityState.PAUSED
12067 || r.state == ActivityState.STOPPING) {
12068 adj = PERCEPTIBLE_APP_ADJ;
12069 app.adjType = "stopping";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012070 }
12071 }
12072 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012073 // A very not-needed process. If this is lower in the lru list,
12074 // we will push it in to the empty bucket.
12075 app.hidden = true;
12076 app.empty = true;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012077 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012078 adj = hiddenAdj;
12079 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012080 }
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012081
12082 if (adj > PERCEPTIBLE_APP_ADJ) {
12083 if (app.foregroundServices) {
12084 // The user is aware of this app, so make it visible.
12085 adj = PERCEPTIBLE_APP_ADJ;
12086 schedGroup = Process.THREAD_GROUP_DEFAULT;
12087 app.adjType = "foreground-service";
12088 } else if (app.forcingToForeground != null) {
12089 // The user is aware of this app, so make it visible.
12090 adj = PERCEPTIBLE_APP_ADJ;
12091 schedGroup = Process.THREAD_GROUP_DEFAULT;
12092 app.adjType = "force-foreground";
12093 app.adjSource = app.forcingToForeground;
12094 }
12095 }
12096
12097 if (adj > HEAVY_WEIGHT_APP_ADJ && app == mHeavyWeightProcess) {
12098 // We don't want to kill the current heavy-weight process.
12099 adj = HEAVY_WEIGHT_APP_ADJ;
12100 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
12101 app.adjType = "heavy";
12102 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012103
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012104 if (adj > HOME_APP_ADJ && app == mHomeProcess) {
12105 // This process is hosting what we currently consider to be the
12106 // home app, so we don't want to let it go into the background.
12107 adj = HOME_APP_ADJ;
12108 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
12109 app.adjType = "home";
12110 }
12111
Joe Onorato8a9b2202010-02-26 18:56:32 -080012112 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012113
The Android Open Source Project4df24232009-03-05 14:34:35 -080012114 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012115 // there are applications dependent on our services or providers, but
12116 // this gives us a baseline and makes sure we don't get into an
12117 // infinite recursion.
12118 app.adjSeq = mAdjSeq;
12119 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012120
Christopher Tate6fa95972009-06-05 18:43:55 -070012121 if (mBackupTarget != null && app == mBackupTarget.app) {
12122 // If possible we want to avoid killing apps while they're being backed up
12123 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012124 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070012125 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012126 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012127 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070012128 }
12129 }
12130
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012131 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
12132 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012133 final long now = SystemClock.uptimeMillis();
12134 // This process is more important if the top activity is
12135 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070012136 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012137 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012138 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012139 if (s.startRequested) {
12140 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
12141 // This service has seen some activity within
12142 // recent memory, so we will keep its process ahead
12143 // of the background processes.
12144 if (adj > SECONDARY_SERVER_ADJ) {
12145 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012146 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012147 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012148 }
12149 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012150 // If we have let the service slide into the background
12151 // state, still have some text describing what it is doing
12152 // even though the service no longer has an impact.
12153 if (adj > SECONDARY_SERVER_ADJ) {
12154 app.adjType = "started-bg-services";
12155 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012156 // Don't kill this process because it is doing work; it
12157 // has said it is doing work.
12158 app.keeping = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012159 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012160 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
12161 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012162 Iterator<ArrayList<ConnectionRecord>> kt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012163 = s.connections.values().iterator();
12164 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012165 ArrayList<ConnectionRecord> clist = kt.next();
12166 for (int i=0; i<clist.size() && adj > FOREGROUND_APP_ADJ; i++) {
12167 // XXX should compute this based on the max of
12168 // all connected clients.
12169 ConnectionRecord cr = clist.get(i);
12170 if (cr.binding.client == app) {
12171 // Binding to ourself is not interesting.
12172 continue;
12173 }
12174 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
12175 ProcessRecord client = cr.binding.client;
12176 int myHiddenAdj = hiddenAdj;
12177 if (myHiddenAdj > client.hiddenAdj) {
12178 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
12179 myHiddenAdj = client.hiddenAdj;
12180 } else {
12181 myHiddenAdj = VISIBLE_APP_ADJ;
12182 }
12183 }
12184 int clientAdj = computeOomAdjLocked(
12185 client, myHiddenAdj, TOP_APP, true);
12186 if (adj > clientAdj) {
12187 adj = clientAdj >= VISIBLE_APP_ADJ
12188 ? clientAdj : VISIBLE_APP_ADJ;
12189 if (!client.hidden) {
12190 app.hidden = false;
12191 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012192 if (client.keeping) {
12193 app.keeping = true;
12194 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012195 app.adjType = "service";
12196 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12197 .REASON_SERVICE_IN_USE;
12198 app.adjSource = cr.binding.client;
12199 app.adjTarget = s.name;
12200 }
12201 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
12202 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
12203 schedGroup = Process.THREAD_GROUP_DEFAULT;
12204 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012205 }
12206 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012207 ActivityRecord a = cr.activity;
12208 //if (a != null) {
12209 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
12210 //}
12211 if (a != null && adj > FOREGROUND_APP_ADJ &&
12212 (a.state == ActivityState.RESUMED
12213 || a.state == ActivityState.PAUSING)) {
12214 adj = FOREGROUND_APP_ADJ;
12215 schedGroup = Process.THREAD_GROUP_DEFAULT;
12216 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012217 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012218 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12219 .REASON_SERVICE_IN_USE;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012220 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012221 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012222 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012223 }
12224 }
12225 }
12226 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012227
Dianne Hackborn287952c2010-09-22 22:34:31 -070012228 // Finally, if this process has active services running in it, we
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012229 // would like to avoid killing it unless it would prevent the current
12230 // application from running. By default we put the process in
12231 // with the rest of the background processes; as we scan through
12232 // its services we may bump it up from there.
12233 if (adj > hiddenAdj) {
12234 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012235 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012236 app.adjType = "bg-services";
12237 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012238 }
12239
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012240 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
12241 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012242 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012243 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
12244 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012245 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012246 if (cpr.clients.size() != 0) {
12247 Iterator<ProcessRecord> kt = cpr.clients.iterator();
12248 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
12249 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070012250 if (client == app) {
12251 // Being our own client is not interesting.
12252 continue;
12253 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012254 int myHiddenAdj = hiddenAdj;
12255 if (myHiddenAdj > client.hiddenAdj) {
12256 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
12257 myHiddenAdj = client.hiddenAdj;
12258 } else {
12259 myHiddenAdj = FOREGROUND_APP_ADJ;
12260 }
12261 }
12262 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012263 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012264 if (adj > clientAdj) {
12265 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012266 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012267 if (!client.hidden) {
12268 app.hidden = false;
12269 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012270 if (client.keeping) {
12271 app.keeping = true;
12272 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012273 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012274 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12275 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012276 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012277 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012278 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012279 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
12280 schedGroup = Process.THREAD_GROUP_DEFAULT;
12281 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012282 }
12283 }
12284 // If the provider has external (non-framework) process
12285 // dependencies, ensure that its adjustment is at least
12286 // FOREGROUND_APP_ADJ.
12287 if (cpr.externals != 0) {
12288 if (adj > FOREGROUND_APP_ADJ) {
12289 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012290 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012291 app.hidden = false;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012292 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012293 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012294 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012295 }
12296 }
12297 }
12298 }
12299
12300 app.curRawAdj = adj;
12301
Joe Onorato8a9b2202010-02-26 18:56:32 -080012302 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012303 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
12304 if (adj > app.maxAdj) {
12305 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070012306 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012307 schedGroup = Process.THREAD_GROUP_DEFAULT;
12308 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012309 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012310 if (adj < HIDDEN_APP_MIN_ADJ) {
12311 app.keeping = true;
12312 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012313
12314 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012315 app.curSchedGroup = schedGroup;
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012316
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012317 return adj;
12318 }
12319
12320 /**
12321 * Ask a given process to GC right now.
12322 */
12323 final void performAppGcLocked(ProcessRecord app) {
12324 try {
12325 app.lastRequestedGc = SystemClock.uptimeMillis();
12326 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012327 if (app.reportLowMemory) {
12328 app.reportLowMemory = false;
12329 app.thread.scheduleLowMemory();
12330 } else {
12331 app.thread.processInBackground();
12332 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012333 }
12334 } catch (Exception e) {
12335 // whatever.
12336 }
12337 }
12338
12339 /**
12340 * Returns true if things are idle enough to perform GCs.
12341 */
Josh Bartel7f208742010-02-25 11:01:44 -060012342 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012343 return mParallelBroadcasts.size() == 0
12344 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012345 && (mSleeping || (mMainStack.mResumedActivity != null &&
12346 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012347 }
12348
12349 /**
12350 * Perform GCs on all processes that are waiting for it, but only
12351 * if things are idle.
12352 */
12353 final void performAppGcsLocked() {
12354 final int N = mProcessesToGc.size();
12355 if (N <= 0) {
12356 return;
12357 }
Josh Bartel7f208742010-02-25 11:01:44 -060012358 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012359 while (mProcessesToGc.size() > 0) {
12360 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070012361 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012362 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
12363 <= SystemClock.uptimeMillis()) {
12364 // To avoid spamming the system, we will GC processes one
12365 // at a time, waiting a few seconds between each.
12366 performAppGcLocked(proc);
12367 scheduleAppGcsLocked();
12368 return;
12369 } else {
12370 // It hasn't been long enough since we last GCed this
12371 // process... put it in the list to wait for its time.
12372 addProcessToGcListLocked(proc);
12373 break;
12374 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012375 }
12376 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012377
12378 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012379 }
12380 }
12381
12382 /**
12383 * If all looks good, perform GCs on all processes waiting for them.
12384 */
12385 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060012386 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012387 performAppGcsLocked();
12388 return;
12389 }
12390 // Still not idle, wait some more.
12391 scheduleAppGcsLocked();
12392 }
12393
12394 /**
12395 * Schedule the execution of all pending app GCs.
12396 */
12397 final void scheduleAppGcsLocked() {
12398 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012399
12400 if (mProcessesToGc.size() > 0) {
12401 // Schedule a GC for the time to the next process.
12402 ProcessRecord proc = mProcessesToGc.get(0);
12403 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
12404
12405 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
12406 long now = SystemClock.uptimeMillis();
12407 if (when < (now+GC_TIMEOUT)) {
12408 when = now + GC_TIMEOUT;
12409 }
12410 mHandler.sendMessageAtTime(msg, when);
12411 }
12412 }
12413
12414 /**
12415 * Add a process to the array of processes waiting to be GCed. Keeps the
12416 * list in sorted order by the last GC time. The process can't already be
12417 * on the list.
12418 */
12419 final void addProcessToGcListLocked(ProcessRecord proc) {
12420 boolean added = false;
12421 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
12422 if (mProcessesToGc.get(i).lastRequestedGc <
12423 proc.lastRequestedGc) {
12424 added = true;
12425 mProcessesToGc.add(i+1, proc);
12426 break;
12427 }
12428 }
12429 if (!added) {
12430 mProcessesToGc.add(0, proc);
12431 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012432 }
12433
12434 /**
12435 * Set up to ask a process to GC itself. This will either do it
12436 * immediately, or put it on the list of processes to gc the next
12437 * time things are idle.
12438 */
12439 final void scheduleAppGcLocked(ProcessRecord app) {
12440 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012441 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012442 return;
12443 }
12444 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012445 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012446 scheduleAppGcsLocked();
12447 }
12448 }
12449
Dianne Hackborn287952c2010-09-22 22:34:31 -070012450 final void checkExcessivePowerUsageLocked(boolean doKills) {
12451 updateCpuStatsNow();
12452
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012453 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
Dianne Hackborn287952c2010-09-22 22:34:31 -070012454 boolean doWakeKills = doKills;
12455 boolean doCpuKills = doKills;
12456 if (mLastPowerCheckRealtime == 0) {
12457 doWakeKills = false;
12458 }
12459 if (mLastPowerCheckUptime == 0) {
12460 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012461 }
12462 if (stats.isScreenOn()) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070012463 doWakeKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012464 }
12465 final long curRealtime = SystemClock.elapsedRealtime();
Dianne Hackborn287952c2010-09-22 22:34:31 -070012466 final long realtimeSince = curRealtime - mLastPowerCheckRealtime;
12467 final long curUptime = SystemClock.uptimeMillis();
12468 final long uptimeSince = curUptime - mLastPowerCheckUptime;
12469 mLastPowerCheckRealtime = curRealtime;
12470 mLastPowerCheckUptime = curUptime;
12471 if (realtimeSince < WAKE_LOCK_MIN_CHECK_DURATION) {
12472 doWakeKills = false;
12473 }
12474 if (uptimeSince < CPU_MIN_CHECK_DURATION) {
12475 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012476 }
12477 int i = mLruProcesses.size();
12478 while (i > 0) {
12479 i--;
12480 ProcessRecord app = mLruProcesses.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012481 if (!app.keeping) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012482 long wtime;
12483 synchronized (stats) {
12484 wtime = stats.getProcessWakeTime(app.info.uid,
12485 app.pid, curRealtime);
12486 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012487 long wtimeUsed = wtime - app.lastWakeTime;
12488 long cputimeUsed = app.curCpuTime - app.lastCpuTime;
12489 if (DEBUG_POWER) {
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012490 StringBuilder sb = new StringBuilder(128);
12491 sb.append("Wake for ");
12492 app.toShortString(sb);
12493 sb.append(": over ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012494 TimeUtils.formatDuration(realtimeSince, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012495 sb.append(" used ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012496 TimeUtils.formatDuration(wtimeUsed, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012497 sb.append(" (");
Dianne Hackborn287952c2010-09-22 22:34:31 -070012498 sb.append((wtimeUsed*100)/realtimeSince);
12499 sb.append("%)");
12500 Slog.i(TAG, sb.toString());
12501 sb.setLength(0);
12502 sb.append("CPU for ");
12503 app.toShortString(sb);
12504 sb.append(": over ");
12505 TimeUtils.formatDuration(uptimeSince, sb);
12506 sb.append(" used ");
12507 TimeUtils.formatDuration(cputimeUsed, sb);
12508 sb.append(" (");
12509 sb.append((cputimeUsed*100)/uptimeSince);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070012510 sb.append("%)");
12511 Slog.i(TAG, sb.toString());
12512 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012513 // If a process has held a wake lock for more
12514 // than 50% of the time during this period,
12515 // that sounds pad. Kill!
Dianne Hackborn287952c2010-09-22 22:34:31 -070012516 if (doWakeKills && realtimeSince > 0
12517 && ((wtimeUsed*100)/realtimeSince) >= 50) {
12518 synchronized (stats) {
12519 stats.reportExcessiveWakeLocked(app.info.uid, app.processName,
12520 realtimeSince, wtimeUsed);
12521 }
12522 Slog.w(TAG, "Excessive wake lock in " + app.processName
12523 + " (pid " + app.pid + "): held " + wtimeUsed
12524 + " during " + realtimeSince);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012525 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12526 app.processName, app.setAdj, "excessive wake lock");
12527 Process.killProcessQuiet(app.pid);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012528 } else if (doCpuKills && uptimeSince > 0
12529 && ((cputimeUsed*100)/uptimeSince) >= 50) {
12530 synchronized (stats) {
12531 stats.reportExcessiveCpuLocked(app.info.uid, app.processName,
12532 uptimeSince, cputimeUsed);
12533 }
12534 Slog.w(TAG, "Excessive CPU in " + app.processName
12535 + " (pid " + app.pid + "): used " + cputimeUsed
12536 + " during " + uptimeSince);
12537 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12538 app.processName, app.setAdj, "excessive cpu");
12539 Process.killProcessQuiet(app.pid);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012540 } else {
12541 app.lastWakeTime = wtime;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012542 app.lastCpuTime = app.curCpuTime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012543 }
12544 }
12545 }
12546 }
12547
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012548 private final boolean updateOomAdjLocked(
12549 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
12550 app.hiddenAdj = hiddenAdj;
12551
12552 if (app.thread == null) {
12553 return true;
12554 }
12555
Dianne Hackborn287952c2010-09-22 22:34:31 -070012556 final boolean wasKeeping = app.keeping;
12557
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012558 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012559
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012560 if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012561 if (app.curRawAdj != app.setRawAdj) {
12562 if (app.curRawAdj > FOREGROUND_APP_ADJ
12563 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
12564 // If this app is transitioning from foreground to
12565 // non-foreground, have it do a gc.
12566 scheduleAppGcLocked(app);
12567 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
12568 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
12569 // Likewise do a gc when an app is moving in to the
12570 // background (such as a service stopping).
12571 scheduleAppGcLocked(app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070012572 }
12573
12574 if (wasKeeping && !app.keeping) {
12575 // This app is no longer something we want to keep. Note
12576 // its current wake lock time to later know to kill it if
12577 // it is not behaving well.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012578 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
12579 synchronized (stats) {
12580 app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
12581 app.pid, SystemClock.elapsedRealtime());
12582 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012583 app.lastCpuTime = app.curCpuTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012584 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012585
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012586 app.setRawAdj = app.curRawAdj;
12587 }
12588 if (adj != app.setAdj) {
12589 if (Process.setOomAdj(app.pid, adj)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012590 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012591 TAG, "Set app " + app.processName +
12592 " oom adj to " + adj);
12593 app.setAdj = adj;
12594 } else {
12595 return false;
12596 }
12597 }
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012598 if (app.setSchedGroup != app.curSchedGroup) {
12599 app.setSchedGroup = app.curSchedGroup;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012600 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012601 "Setting process group of " + app.processName
12602 + " to " + app.curSchedGroup);
12603 if (true) {
San Mehat9438de22009-06-10 09:11:28 -070012604 long oldId = Binder.clearCallingIdentity();
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012605 try {
12606 Process.setProcessGroup(app.pid, app.curSchedGroup);
12607 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012608 Slog.w(TAG, "Failed setting process group of " + app.pid
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012609 + " to " + app.curSchedGroup);
San Mehat9438de22009-06-10 09:11:28 -070012610 e.printStackTrace();
12611 } finally {
12612 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070012613 }
12614 }
12615 if (false) {
12616 if (app.thread != null) {
12617 try {
12618 app.thread.setSchedulingGroup(app.curSchedGroup);
12619 } catch (RemoteException e) {
12620 }
12621 }
12622 }
12623 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012624 }
12625
12626 return true;
12627 }
12628
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012629 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012630 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012631 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012632 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012633 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012634 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012635 }
12636 }
12637 return resumedActivity;
12638 }
12639
12640 private final boolean updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012641 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012642 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
12643 int curAdj = app.curAdj;
12644 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
12645 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
12646
12647 mAdjSeq++;
12648
12649 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
12650 if (res) {
12651 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
12652 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
12653 if (nowHidden != wasHidden) {
12654 // Changed to/from hidden state, so apps after it in the LRU
12655 // list may also be changed.
12656 updateOomAdjLocked();
12657 }
12658 }
12659 return res;
12660 }
12661
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012662 final boolean updateOomAdjLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012663 boolean didOomAdj = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012664 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012665 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
12666
12667 if (false) {
12668 RuntimeException e = new RuntimeException();
12669 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080012670 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012671 }
12672
12673 mAdjSeq++;
12674
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012675 // Let's determine how many processes we have running vs.
12676 // how many slots we have for background processes; we may want
12677 // to put multiple processes in a slot of there are enough of
12678 // them.
12679 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
12680 int factor = (mLruProcesses.size()-4)/numSlots;
12681 if (factor < 1) factor = 1;
12682 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070012683 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012684
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012685 // First try updating the OOM adjustment for each of the
12686 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012687 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012688 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
12689 while (i > 0) {
12690 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012691 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012692 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012693 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012694 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012695 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012696 step++;
12697 if (step >= factor) {
12698 step = 0;
12699 curHiddenAdj++;
12700 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012701 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070012702 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070012703 if (!app.killedBackground) {
12704 numHidden++;
12705 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070012706 Slog.i(TAG, "No longer want " + app.processName
12707 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070012708 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
12709 app.processName, app.setAdj, "too many background");
12710 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070012711 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070012712 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070012713 }
12714 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012715 } else {
12716 didOomAdj = false;
12717 }
12718 }
12719
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012720 // If we return false, we will fall back on killing processes to
12721 // have a fixed limit. Do this if a limit has been requested; else
12722 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012723 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
12724 }
12725
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012726 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012727 synchronized (this) {
12728 int i;
12729
12730 // First remove any unused application processes whose package
12731 // has been removed.
12732 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
12733 final ProcessRecord app = mRemovedProcesses.get(i);
12734 if (app.activities.size() == 0
12735 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012736 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012737 TAG, "Exiting empty application process "
12738 + app.processName + " ("
12739 + (app.thread != null ? app.thread.asBinder() : null)
12740 + ")\n");
12741 if (app.pid > 0 && app.pid != MY_PID) {
12742 Process.killProcess(app.pid);
12743 } else {
12744 try {
12745 app.thread.scheduleExit();
12746 } catch (Exception e) {
12747 // Ignore exceptions.
12748 }
12749 }
12750 cleanUpApplicationRecordLocked(app, false, -1);
12751 mRemovedProcesses.remove(i);
12752
12753 if (app.persistent) {
12754 if (app.persistent) {
12755 addAppLocked(app.info);
12756 }
12757 }
12758 }
12759 }
12760
12761 // Now try updating the OOM adjustment for each of the
12762 // application processes based on their current state.
12763 // If the setOomAdj() API is not supported, then go with our
12764 // back-up plan...
12765 if (!updateOomAdjLocked()) {
12766
12767 // Count how many processes are running services.
12768 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012769 for (i=mLruProcesses.size()-1; i>=0; i--) {
12770 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012771
12772 if (app.persistent || app.services.size() != 0
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012773 || app.curReceiver != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012774 // Don't count processes holding services against our
12775 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012776 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012777 TAG, "Not trimming app " + app + " with services: "
12778 + app.services);
12779 numServiceProcs++;
12780 }
12781 }
12782
12783 int curMaxProcs = mProcessLimit;
12784 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
12785 if (mAlwaysFinishActivities) {
12786 curMaxProcs = 1;
12787 }
12788 curMaxProcs += numServiceProcs;
12789
12790 // Quit as many processes as we can to get down to the desired
12791 // process count. First remove any processes that no longer
12792 // have activites running in them.
12793 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012794 i<mLruProcesses.size()
12795 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012796 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012797 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012798 // Quit an application only if it is not currently
12799 // running any activities.
12800 if (!app.persistent && app.activities.size() == 0
12801 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012802 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012803 TAG, "Exiting empty application process "
12804 + app.processName + " ("
12805 + (app.thread != null ? app.thread.asBinder() : null)
12806 + ")\n");
12807 if (app.pid > 0 && app.pid != MY_PID) {
12808 Process.killProcess(app.pid);
12809 } else {
12810 try {
12811 app.thread.scheduleExit();
12812 } catch (Exception e) {
12813 // Ignore exceptions.
12814 }
12815 }
12816 // todo: For now we assume the application is not buggy
12817 // or evil, and will quit as a result of our request.
12818 // Eventually we need to drive this off of the death
12819 // notification, and kill the process if it takes too long.
12820 cleanUpApplicationRecordLocked(app, false, i);
12821 i--;
12822 }
12823 }
12824
12825 // If we still have too many processes, now from the least
12826 // recently used process we start finishing activities.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012827 if (Config.LOGV) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012828 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012829 " of " + curMaxProcs + " processes");
12830 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012831 i<mLruProcesses.size()
12832 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012833 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012834 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012835 // Quit the application only if we have a state saved for
12836 // all of its activities.
12837 boolean canQuit = !app.persistent && app.curReceiver == null
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012838 && app.services.size() == 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012839 int NUMA = app.activities.size();
12840 int j;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012841 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012842 TAG, "Looking to quit " + app.processName);
12843 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012844 ActivityRecord r = app.activities.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012845 if (Config.LOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012846 TAG, " " + r.intent.getComponent().flattenToShortString()
12847 + ": frozen=" + r.haveState + ", visible=" + r.visible);
12848 canQuit = (r.haveState || !r.stateNotNeeded)
12849 && !r.visible && r.stopped;
12850 }
12851 if (canQuit) {
12852 // Finish all of the activities, and then the app itself.
12853 for (j=0; j<NUMA; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012854 ActivityRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012855 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012856 r.stack.destroyActivityLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012857 }
12858 r.resultTo = null;
12859 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080012860 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012861 + app.processName + " ("
12862 + (app.thread != null ? app.thread.asBinder() : null)
12863 + ")\n");
12864 if (app.pid > 0 && app.pid != MY_PID) {
12865 Process.killProcess(app.pid);
12866 } else {
12867 try {
12868 app.thread.scheduleExit();
12869 } catch (Exception e) {
12870 // Ignore exceptions.
12871 }
12872 }
12873 // todo: For now we assume the application is not buggy
12874 // or evil, and will quit as a result of our request.
12875 // Eventually we need to drive this off of the death
12876 // notification, and kill the process if it takes too long.
12877 cleanUpApplicationRecordLocked(app, false, i);
12878 i--;
12879 //dump();
12880 }
12881 }
12882
12883 }
12884
12885 int curMaxActivities = MAX_ACTIVITIES;
12886 if (mAlwaysFinishActivities) {
12887 curMaxActivities = 1;
12888 }
12889
12890 // Finally, if there are too many activities now running, try to
12891 // finish as many as we can to get back down to the limit.
12892 for ( i=0;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012893 i<mMainStack.mLRUActivities.size()
12894 && mMainStack.mLRUActivities.size() > curMaxActivities;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012895 i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012896 final ActivityRecord r
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012897 = (ActivityRecord)mMainStack.mLRUActivities.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012898
12899 // We can finish this one if we have its icicle saved and
12900 // it is not persistent.
12901 if ((r.haveState || !r.stateNotNeeded) && !r.visible
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070012902 && r.stopped && !r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012903 final int origSize = mMainStack.mLRUActivities.size();
12904 r.stack.destroyActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012905
12906 // This will remove it from the LRU list, so keep
12907 // our index at the same value. Note that this check to
12908 // see if the size changes is just paranoia -- if
12909 // something unexpected happens, we don't want to end up
12910 // in an infinite loop.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012911 if (origSize > mMainStack.mLRUActivities.size()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012912 i--;
12913 }
12914 }
12915 }
12916 }
12917 }
12918
12919 /** This method sends the specified signal to each of the persistent apps */
12920 public void signalPersistentProcesses(int sig) throws RemoteException {
12921 if (sig != Process.SIGNAL_USR1) {
12922 throw new SecurityException("Only SIGNAL_USR1 is allowed");
12923 }
12924
12925 synchronized (this) {
12926 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
12927 != PackageManager.PERMISSION_GRANTED) {
12928 throw new SecurityException("Requires permission "
12929 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
12930 }
12931
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012932 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
12933 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012934 if (r.thread != null && r.persistent) {
12935 Process.sendSignal(r.pid, sig);
12936 }
12937 }
12938 }
12939 }
12940
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012941 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012942 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012943
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012944 try {
12945 synchronized (this) {
12946 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
12947 // its own permission.
12948 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
12949 != PackageManager.PERMISSION_GRANTED) {
12950 throw new SecurityException("Requires permission "
12951 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012952 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012953
12954 if (start && fd == null) {
12955 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012956 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012957
12958 ProcessRecord proc = null;
12959 try {
12960 int pid = Integer.parseInt(process);
12961 synchronized (mPidsSelfLocked) {
12962 proc = mPidsSelfLocked.get(pid);
12963 }
12964 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012965 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012966
12967 if (proc == null) {
12968 HashMap<String, SparseArray<ProcessRecord>> all
12969 = mProcessNames.getMap();
12970 SparseArray<ProcessRecord> procs = all.get(process);
12971 if (procs != null && procs.size() > 0) {
12972 proc = procs.valueAt(0);
12973 }
12974 }
12975
12976 if (proc == null || proc.thread == null) {
12977 throw new IllegalArgumentException("Unknown process: " + process);
12978 }
12979
Dianne Hackbornf02e57b2011-03-01 22:21:04 -080012980 boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
12981 if (!isDebuggable) {
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012982 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
12983 throw new SecurityException("Process not debuggable: " + proc);
12984 }
12985 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012986
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012987 proc.thread.profilerControl(start, path, fd);
12988 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012989 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070012990 }
12991 } catch (RemoteException e) {
12992 throw new IllegalStateException("Process disappeared");
12993 } finally {
12994 if (fd != null) {
12995 try {
12996 fd.close();
12997 } catch (IOException e) {
12998 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080012999 }
13000 }
13001 }
Andy McFadden824c5102010-07-09 16:26:57 -070013002
13003 public boolean dumpHeap(String process, boolean managed,
13004 String path, ParcelFileDescriptor fd) throws RemoteException {
13005
13006 try {
13007 synchronized (this) {
13008 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
13009 // its own permission (same as profileControl).
13010 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
13011 != PackageManager.PERMISSION_GRANTED) {
13012 throw new SecurityException("Requires permission "
13013 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
13014 }
13015
13016 if (fd == null) {
13017 throw new IllegalArgumentException("null fd");
13018 }
13019
13020 ProcessRecord proc = null;
13021 try {
13022 int pid = Integer.parseInt(process);
13023 synchronized (mPidsSelfLocked) {
13024 proc = mPidsSelfLocked.get(pid);
13025 }
13026 } catch (NumberFormatException e) {
13027 }
13028
13029 if (proc == null) {
13030 HashMap<String, SparseArray<ProcessRecord>> all
13031 = mProcessNames.getMap();
13032 SparseArray<ProcessRecord> procs = all.get(process);
13033 if (procs != null && procs.size() > 0) {
13034 proc = procs.valueAt(0);
13035 }
13036 }
13037
13038 if (proc == null || proc.thread == null) {
13039 throw new IllegalArgumentException("Unknown process: " + process);
13040 }
13041
Dianne Hackbornf02e57b2011-03-01 22:21:04 -080013042 boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
13043 if (!isDebuggable) {
Andy McFadden824c5102010-07-09 16:26:57 -070013044 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
13045 throw new SecurityException("Process not debuggable: " + proc);
13046 }
13047 }
13048
13049 proc.thread.dumpHeap(managed, path, fd);
13050 fd = null;
13051 return true;
13052 }
13053 } catch (RemoteException e) {
13054 throw new IllegalStateException("Process disappeared");
13055 } finally {
13056 if (fd != null) {
13057 try {
13058 fd.close();
13059 } catch (IOException e) {
13060 }
13061 }
13062 }
13063 }
13064
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013065 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
13066 public void monitor() {
13067 synchronized (this) { }
13068 }
Svetoslav Ganov54d068e2011-03-02 12:58:40 -080013069
13070 public void onCoreSettingsChange(Bundle settings) {
13071 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
13072 ProcessRecord processRecord = mLruProcesses.get(i);
13073 try {
13074 if (processRecord.thread != null) {
13075 processRecord.thread.setCoreSettings(settings);
13076 }
13077 } catch (RemoteException re) {
13078 /* ignore */
13079 }
13080 }
13081 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013082}