blob: 8501163e82a70d46084c066be5a4db236e2e0853 [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;
Jeff Sharkeya4620792011-05-20 15:29:23 -070045import android.app.IProcessObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046import android.app.IServiceConnection;
47import android.app.IThumbnailReceiver;
Dianne Hackbornf26fd992011-04-08 18:14:09 -070048import android.app.IThumbnailRetriever;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080049import android.app.Instrumentation;
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070050import android.app.Notification;
Dianne Hackborn860755f2010-06-03 18:47:52 -070051import android.app.NotificationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052import android.app.PendingIntent;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070053import android.app.Service;
Christopher Tate45281862010-03-05 15:46:30 -080054import android.app.backup.IBackupManager;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020055import android.content.ActivityNotFoundException;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080056import android.content.BroadcastReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080057import android.content.ComponentName;
58import android.content.ContentResolver;
59import android.content.Context;
Christian Mehlmauer7664e202010-07-20 08:46:17 +020060import android.content.DialogInterface;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080061import android.content.Intent;
62import android.content.IntentFilter;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070063import android.content.IIntentReceiver;
64import android.content.IIntentSender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -070065import android.content.IntentSender;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080066import android.content.pm.ActivityInfo;
67import android.content.pm.ApplicationInfo;
68import android.content.pm.ConfigurationInfo;
69import android.content.pm.IPackageDataObserver;
70import android.content.pm.IPackageManager;
71import android.content.pm.InstrumentationInfo;
Dan Egnor66c40e72010-01-26 16:23:11 -080072import android.content.pm.PackageInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080073import android.content.pm.PackageManager;
Dianne Hackborn2af632f2009-07-08 14:56:37 -070074import android.content.pm.PathPermission;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080075import android.content.pm.ProviderInfo;
76import android.content.pm.ResolveInfo;
77import android.content.pm.ServiceInfo;
Dianne Hackborn860755f2010-06-03 18:47:52 -070078import android.content.pm.PackageManager.NameNotFoundException;
Dianne Hackborne2515ee2011-04-27 18:52:56 -040079import android.content.res.CompatibilityInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080080import android.content.res.Configuration;
81import android.graphics.Bitmap;
Robert Greenwalt434203a2010-10-11 16:00:27 -070082import android.net.Proxy;
83import android.net.ProxyProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080084import android.net.Uri;
85import android.os.Binder;
Dan Egnor60d87622009-12-16 16:32:58 -080086import android.os.Build;
Dan Egnor42471dd2010-01-07 17:25:22 -080087import android.os.Bundle;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070088import android.os.Debug;
Dan Egnor60d87622009-12-16 16:32:58 -080089import android.os.DropBoxManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080090import android.os.Environment;
Dan Egnor42471dd2010-01-07 17:25:22 -080091import android.os.FileObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080092import android.os.FileUtils;
93import android.os.Handler;
94import android.os.IBinder;
95import android.os.IPermissionController;
96import android.os.Looper;
97import android.os.Message;
98import android.os.Parcel;
99import android.os.ParcelFileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800100import android.os.Process;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700101import android.os.RemoteCallbackList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102import android.os.RemoteException;
103import android.os.ServiceManager;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -0700104import android.os.StrictMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800105import android.os.SystemClock;
106import android.os.SystemProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800107import android.provider.Settings;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800108import android.util.EventLog;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800109import android.util.Slog;
Joe Onorato5d3bea62010-03-01 13:44:29 -0800110import android.util.Log;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800111import android.util.PrintWriterPrinter;
112import android.util.SparseArray;
Dianne Hackborn1ebccf52010-08-15 13:04:34 -0700113import android.util.TimeUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800114import android.view.Gravity;
115import android.view.LayoutInflater;
116import android.view.View;
117import android.view.WindowManager;
118import android.view.WindowManagerPolicy;
119
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700120import java.io.BufferedInputStream;
121import java.io.BufferedOutputStream;
122import java.io.DataInputStream;
123import java.io.DataOutputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800124import java.io.File;
125import java.io.FileDescriptor;
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700126import java.io.FileInputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800127import java.io.FileNotFoundException;
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700128import java.io.FileOutputStream;
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200129import java.io.IOException;
Dan Egnora455d192010-03-12 08:52:28 -0800130import java.io.InputStreamReader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800131import java.io.PrintWriter;
132import java.lang.IllegalStateException;
133import java.lang.ref.WeakReference;
134import java.util.ArrayList;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700135import java.util.Collections;
136import java.util.Comparator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800137import java.util.HashMap;
138import java.util.HashSet;
139import java.util.Iterator;
140import java.util.List;
141import java.util.Locale;
142import java.util.Map;
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -0700143import java.util.Set;
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700144import java.util.concurrent.atomic.AtomicBoolean;
145import java.util.concurrent.atomic.AtomicLong;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800146
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700147public final class ActivityManagerService extends ActivityManagerNative
148 implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800149 static final String TAG = "ActivityManager";
150 static final boolean DEBUG = false;
Dianne Hackborne2515ee2011-04-27 18:52:56 -0400151 static final boolean localLOGV = DEBUG;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800152 static final boolean DEBUG_SWITCH = localLOGV || false;
153 static final boolean DEBUG_TASKS = localLOGV || false;
154 static final boolean DEBUG_PAUSE = localLOGV || false;
155 static final boolean DEBUG_OOM_ADJ = localLOGV || false;
156 static final boolean DEBUG_TRANSITION = localLOGV || false;
157 static final boolean DEBUG_BROADCAST = localLOGV || false;
Dianne Hackborn82f3f002009-06-16 18:49:05 -0700158 static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800159 static final boolean DEBUG_SERVICE = localLOGV || false;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700160 static final boolean DEBUG_SERVICE_EXECUTING = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800161 static final boolean DEBUG_VISBILITY = localLOGV || false;
162 static final boolean DEBUG_PROCESSES = localLOGV || false;
Dianne Hackborna1e989b2009-09-01 19:54:29 -0700163 static final boolean DEBUG_PROVIDER = localLOGV || false;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800164 static final boolean DEBUG_URI_PERMISSION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800165 static final boolean DEBUG_USER_LEAVING = localLOGV || false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700166 static final boolean DEBUG_RESULTS = localLOGV || false;
Christopher Tate4a627c72011-04-01 14:43:32 -0700167 static final boolean DEBUG_BACKUP = localLOGV || true;
Dianne Hackborndc6b6352009-09-30 14:20:09 -0700168 static final boolean DEBUG_CONFIGURATION = localLOGV || false;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700169 static final boolean DEBUG_POWER = localLOGV || false;
170 static final boolean DEBUG_POWER_QUICK = DEBUG_POWER || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800171 static final boolean VALIDATE_TOKENS = false;
172 static final boolean SHOW_ACTIVITY_START_TIME = true;
173
174 // Control over CPU and battery monitoring.
175 static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes.
176 static final boolean MONITOR_CPU_USAGE = true;
177 static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds.
178 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample.
179 static final boolean MONITOR_THREAD_CPU_USAGE = false;
180
Dianne Hackborn1655be42009-05-08 14:29:01 -0700181 // The flags that are set for all calls we make to the package manager.
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700182 static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
Dianne Hackborn1655be42009-05-08 14:29:01 -0700183
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800184 private static final String SYSTEM_SECURE = "ro.secure";
Dianne Hackbornf02e57b2011-03-01 22:21:04 -0800185 private static final String SYSTEM_DEBUGGABLE = "ro.debuggable";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800186
187 // This is the maximum number of application processes we would like
188 // to have running. Due to the asynchronous nature of things, we can
189 // temporarily go beyond this limit.
190 static final int MAX_PROCESSES = 2;
191
192 // Set to false to leave processes running indefinitely, relying on
193 // the kernel killing them as resources are required.
194 static final boolean ENFORCE_PROCESS_LIMIT = false;
195
196 // This is the maximum number of activities that we would like to have
197 // running at a given time.
198 static final int MAX_ACTIVITIES = 20;
199
200 // Maximum number of recent tasks that we can remember.
201 static final int MAX_RECENT_TASKS = 20;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700202
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700203 // Amount of time after a call to stopAppSwitches() during which we will
204 // prevent further untrusted switches from happening.
205 static final long APP_SWITCH_DELAY_TIME = 5*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800206
207 // How long we wait for a launched process to attach to the activity manager
208 // before we decide it's never going to come up for real.
209 static final int PROC_START_TIMEOUT = 10*1000;
210
Jeff Brown3f9dd282011-07-08 20:02:19 -0700211 // How long we wait for a launched process to attach to the activity manager
212 // before we decide it's never going to come up for real, when the process was
213 // started with a wrapper for instrumentation (such as Valgrind) because it
214 // could take much longer than usual.
215 static final int PROC_START_TIMEOUT_WITH_WRAPPER = 300*1000;
216
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800217 // How long to wait after going idle before forcing apps to GC.
218 static final int GC_TIMEOUT = 5*1000;
219
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700220 // The minimum amount of time between successive GC requests for a process.
221 static final int GC_MIN_INTERVAL = 60*1000;
222
Dianne Hackborn287952c2010-09-22 22:34:31 -0700223 // The rate at which we check for apps using excessive power -- 15 mins.
224 static final int POWER_CHECK_DELAY = (DEBUG_POWER_QUICK ? 2 : 15) * 60*1000;
225
226 // The minimum sample duration we will allow before deciding we have
227 // enough data on wake locks to start killing things.
228 static final int WAKE_LOCK_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
229
230 // The minimum sample duration we will allow before deciding we have
231 // enough data on CPU usage to start killing things.
232 static final int CPU_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700233
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800234 // How long we allow a receiver to run before giving up on it.
235 static final int BROADCAST_TIMEOUT = 10*1000;
236
237 // How long we wait for a service to finish executing.
238 static final int SERVICE_TIMEOUT = 20*1000;
239
240 // How long a service needs to be running until restarting its process
241 // is no longer considered to be a relaunch of the service.
242 static final int SERVICE_RESTART_DURATION = 5*1000;
243
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700244 // How long a service needs to be running until it will start back at
245 // SERVICE_RESTART_DURATION after being killed.
246 static final int SERVICE_RESET_RUN_DURATION = 60*1000;
247
248 // Multiplying factor to increase restart duration time by, for each time
249 // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
250 static final int SERVICE_RESTART_DURATION_FACTOR = 4;
251
252 // The minimum amount of time between restarting services that we allow.
253 // That is, when multiple services are restarting, we won't allow each
254 // to restart less than this amount of time from the last one.
255 static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
256
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800257 // Maximum amount of time for there to be no activity on a service before
258 // we consider it non-essential and allow its process to go on the
259 // LRU background list.
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700260 static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800261
262 // How long we wait until we timeout on key dispatching.
263 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
264
265 // The minimum time we allow between crashes, for us to consider this
266 // application to be bad and stop and its services and reject broadcasts.
267 static final int MIN_CRASH_INTERVAL = 60*1000;
268
269 // How long we wait until we timeout on key dispatching during instrumentation.
270 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
271
272 // OOM adjustments for processes in various states:
273
274 // This is a process without anything currently running in it. Definitely
275 // the first to go! Value set in system/rootdir/init.rc on startup.
276 // This value is initalized in the constructor, careful when refering to
277 // this static variable externally.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800278 static final int EMPTY_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800279
280 // This is a process only hosting activities that are not visible,
281 // so it can be killed without any disruption. Value set in
282 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800283 static final int HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800284 static int HIDDEN_APP_MIN_ADJ;
285
The Android Open Source Project4df24232009-03-05 14:34:35 -0800286 // This is a process holding the home application -- we want to try
287 // avoiding killing it, even if it would normally be in the background,
288 // because the user interacts with it so much.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800289 static final int HOME_APP_ADJ;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800290
Christopher Tate6fa95972009-06-05 18:43:55 -0700291 // This is a process currently hosting a backup operation. Killing it
292 // is not entirely fatal but is generally a bad idea.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800293 static final int BACKUP_APP_ADJ;
Christopher Tate6fa95972009-06-05 18:43:55 -0700294
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800295 // This is a process holding a secondary server -- killing it will not
296 // have much of an impact as far as the user is concerned. Value set in
297 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800298 static final int SECONDARY_SERVER_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800299
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700300 // This is a process with a heavy-weight application. It is in the
301 // background, but we want to try to avoid killing it. Value set in
302 // system/rootdir/init.rc on startup.
303 static final int HEAVY_WEIGHT_APP_ADJ;
304
305 // This is a process only hosting components that are perceptible to the
306 // user, and we really want to avoid killing them, but they are not
307 // immediately visible. An example is background music playback. Value set in
308 // system/rootdir/init.rc on startup.
309 static final int PERCEPTIBLE_APP_ADJ;
310
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800311 // This is a process only hosting activities that are visible to the
312 // user, so we'd prefer they don't disappear. Value set in
313 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800314 static final int VISIBLE_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800315
316 // This is the process running the current foreground app. We'd really
317 // rather not kill it! Value set in system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800318 static final int FOREGROUND_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800319
320 // This is a process running a core server, such as telephony. Definitely
321 // don't want to kill it, but doing so is not completely fatal.
322 static final int CORE_SERVER_ADJ = -12;
323
324 // The system process runs at the default adjustment.
325 static final int SYSTEM_ADJ = -16;
326
327 // Memory pages are 4K.
328 static final int PAGE_SIZE = 4*1024;
329
330 // Corresponding memory levels for above adjustments.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800331 static final int EMPTY_APP_MEM;
332 static final int HIDDEN_APP_MEM;
333 static final int HOME_APP_MEM;
334 static final int BACKUP_APP_MEM;
335 static final int SECONDARY_SERVER_MEM;
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700336 static final int HEAVY_WEIGHT_APP_MEM;
337 static final int PERCEPTIBLE_APP_MEM;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800338 static final int VISIBLE_APP_MEM;
339 static final int FOREGROUND_APP_MEM;
340
341 // The minimum number of hidden apps we want to be able to keep around,
342 // without empty apps being able to push them out of memory.
343 static final int MIN_HIDDEN_APPS = 2;
344
Dianne Hackborn8633e682010-04-22 16:03:41 -0700345 // The maximum number of hidden processes we will keep around before
346 // killing them; this is just a control to not let us go too crazy with
347 // keeping around processes on devices with large amounts of RAM.
348 static final int MAX_HIDDEN_APPS = 15;
349
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800350 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700351 // been idle for less than 15 seconds.
352 static final long CONTENT_APP_IDLE_OFFSET = 15*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800353
354 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700355 // been idle for less than 120 seconds.
356 static final long EMPTY_APP_IDLE_OFFSET = 120*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800357
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700358 static int getIntProp(String name, boolean allowZero) {
359 String str = SystemProperties.get(name);
360 if (str == null) {
361 throw new IllegalArgumentException("Property not defined: " + name);
362 }
363 int val = Integer.valueOf(str);
364 if (val == 0 && !allowZero) {
365 throw new IllegalArgumentException("Property must not be zero: " + name);
366 }
367 return val;
368 }
369
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800370 static {
371 // These values are set in system/rootdir/init.rc on startup.
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700372 FOREGROUND_APP_ADJ = getIntProp("ro.FOREGROUND_APP_ADJ", true);
373 VISIBLE_APP_ADJ = getIntProp("ro.VISIBLE_APP_ADJ", true);
374 PERCEPTIBLE_APP_ADJ = getIntProp("ro.PERCEPTIBLE_APP_ADJ", true);
375 HEAVY_WEIGHT_APP_ADJ = getIntProp("ro.HEAVY_WEIGHT_APP_ADJ", true);
376 SECONDARY_SERVER_ADJ = getIntProp("ro.SECONDARY_SERVER_ADJ", true);
377 BACKUP_APP_ADJ = getIntProp("ro.BACKUP_APP_ADJ", true);
378 HOME_APP_ADJ = getIntProp("ro.HOME_APP_ADJ", true);
379 HIDDEN_APP_MIN_ADJ = getIntProp("ro.HIDDEN_APP_MIN_ADJ", true);
380 EMPTY_APP_ADJ = getIntProp("ro.EMPTY_APP_ADJ", true);
381 // These days we use the last empty slot for hidden apps as well.
382 HIDDEN_APP_MAX_ADJ = EMPTY_APP_ADJ;
383 FOREGROUND_APP_MEM = getIntProp("ro.FOREGROUND_APP_MEM", false)*PAGE_SIZE;
384 VISIBLE_APP_MEM = getIntProp("ro.VISIBLE_APP_MEM", false)*PAGE_SIZE;
385 PERCEPTIBLE_APP_MEM = getIntProp("ro.PERCEPTIBLE_APP_MEM", false)*PAGE_SIZE;
386 HEAVY_WEIGHT_APP_MEM = getIntProp("ro.HEAVY_WEIGHT_APP_MEM", false)*PAGE_SIZE;
387 SECONDARY_SERVER_MEM = getIntProp("ro.SECONDARY_SERVER_MEM", false)*PAGE_SIZE;
388 BACKUP_APP_MEM = getIntProp("ro.BACKUP_APP_MEM", false)*PAGE_SIZE;
389 HOME_APP_MEM = getIntProp("ro.HOME_APP_MEM", false)*PAGE_SIZE;
390 HIDDEN_APP_MEM = getIntProp("ro.HIDDEN_APP_MEM", false)*PAGE_SIZE;
391 EMPTY_APP_MEM = getIntProp("ro.EMPTY_APP_MEM", false)*PAGE_SIZE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800392 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800393
Dan Egnor42471dd2010-01-07 17:25:22 -0800394 static final int MY_PID = Process.myPid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800395
396 static final String[] EMPTY_STRING_ARRAY = new String[0];
397
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700398 public ActivityStack mMainStack;
399
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800400 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700401 * Description of a request to start a new activity, which has been held
402 * due to app switches being disabled.
403 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700404 static class PendingActivityLaunch {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700405 ActivityRecord r;
406 ActivityRecord sourceRecord;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700407 Uri[] grantedUriPermissions;
408 int grantedMode;
409 boolean onlyIfNeeded;
410 }
411
412 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
413 = new ArrayList<PendingActivityLaunch>();
414
415 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800416 * List of all active broadcasts that are to be executed immediately
417 * (without waiting for another broadcast to finish). Currently this only
418 * contains broadcasts to registered receivers, to avoid spinning up
419 * a bunch of processes to execute IntentReceiver components.
420 */
421 final ArrayList<BroadcastRecord> mParallelBroadcasts
422 = new ArrayList<BroadcastRecord>();
423
424 /**
425 * List of all active broadcasts that are to be executed one at a time.
426 * The object at the top of the list is the currently activity broadcasts;
427 * those after it are waiting for the top to finish..
428 */
429 final ArrayList<BroadcastRecord> mOrderedBroadcasts
430 = new ArrayList<BroadcastRecord>();
431
432 /**
Dianne Hackborn12527f92009-11-11 17:39:50 -0800433 * Historical data of past broadcasts, for debugging.
434 */
435 static final int MAX_BROADCAST_HISTORY = 100;
436 final BroadcastRecord[] mBroadcastHistory
437 = new BroadcastRecord[MAX_BROADCAST_HISTORY];
438
439 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800440 * Set when we current have a BROADCAST_INTENT_MSG in flight.
441 */
442 boolean mBroadcastsScheduled = false;
443
444 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800445 * Activity we have told the window manager to have key focus.
446 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700447 ActivityRecord mFocusedActivity = null;
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700448 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800449 * List of intents that were used to start the most recent tasks.
450 */
Dianne Hackborn0c5001d2011-04-12 18:16:08 -0700451 final ArrayList<TaskRecord> mRecentTasks = new ArrayList<TaskRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800452
453 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800454 * All of the applications we currently have running organized by name.
455 * The keys are strings of the application package name (as
456 * returned by the package manager), and the keys are ApplicationRecord
457 * objects.
458 */
Dianne Hackborn0c5001d2011-04-12 18:16:08 -0700459 final ProcessMap<ProcessRecord> mProcessNames = new ProcessMap<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800460
461 /**
Dianne Hackborn860755f2010-06-03 18:47:52 -0700462 * The currently running heavy-weight process, if any.
463 */
464 ProcessRecord mHeavyWeightProcess = null;
465
466 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800467 * The last time that various processes have crashed.
468 */
469 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
470
471 /**
472 * Set of applications that we consider to be bad, and will reject
473 * incoming broadcasts from (which the user has no control over).
474 * Processes are added to this set when they have crashed twice within
475 * a minimum amount of time; they are removed from it when they are
476 * later restarted (hopefully due to some user action). The value is the
477 * time it was added to the list.
478 */
479 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
480
481 /**
482 * All of the processes we currently have running organized by pid.
483 * The keys are the pid running the application.
484 *
485 * <p>NOTE: This object is protected by its own lock, NOT the global
486 * activity manager lock!
487 */
Dianne Hackborn0c5001d2011-04-12 18:16:08 -0700488 final SparseArray<ProcessRecord> mPidsSelfLocked = new SparseArray<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800489
490 /**
491 * All of the processes that have been forced to be foreground. The key
492 * is the pid of the caller who requested it (we hold a death
493 * link on it).
494 */
495 abstract class ForegroundToken implements IBinder.DeathRecipient {
496 int pid;
497 IBinder token;
498 }
499 final SparseArray<ForegroundToken> mForegroundProcesses
500 = new SparseArray<ForegroundToken>();
501
502 /**
503 * List of records for processes that someone had tried to start before the
504 * system was ready. We don't start them at that point, but ensure they
505 * are started by the time booting is complete.
506 */
507 final ArrayList<ProcessRecord> mProcessesOnHold
508 = new ArrayList<ProcessRecord>();
509
510 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800511 * List of persistent applications that are in the process
512 * of being started.
513 */
514 final ArrayList<ProcessRecord> mPersistentStartingProcesses
515 = new ArrayList<ProcessRecord>();
516
517 /**
518 * Processes that are being forcibly torn down.
519 */
520 final ArrayList<ProcessRecord> mRemovedProcesses
521 = new ArrayList<ProcessRecord>();
522
523 /**
524 * List of running applications, sorted by recent usage.
525 * The first entry in the list is the least recently used.
526 * It contains ApplicationRecord objects. This list does NOT include
527 * any persistent application records (since we never want to exit them).
528 */
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800529 final ArrayList<ProcessRecord> mLruProcesses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800530 = new ArrayList<ProcessRecord>();
531
532 /**
533 * List of processes that should gc as soon as things are idle.
534 */
535 final ArrayList<ProcessRecord> mProcessesToGc
536 = new ArrayList<ProcessRecord>();
537
538 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -0800539 * This is the process holding what we currently consider to be
540 * the "home" activity.
541 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700542 ProcessRecord mHomeProcess;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800543
544 /**
Dianne Hackborne2515ee2011-04-27 18:52:56 -0400545 * Packages that the user has asked to have run in screen size
546 * compatibility mode instead of filling the screen.
547 */
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -0700548 final CompatModePackages mCompatModePackages;
Dianne Hackborne2515ee2011-04-27 18:52:56 -0400549
550 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800551 * Set of PendingResultRecord objects that are currently active.
552 */
553 final HashSet mPendingResultRecords = new HashSet();
554
555 /**
556 * Set of IntentSenderRecord objects that are currently active.
557 */
558 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
559 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
560
561 /**
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -0800562 * Fingerprints (hashCode()) of stack traces that we've
Brad Fitzpatrick143666f2010-06-14 12:40:21 -0700563 * already logged DropBox entries for. Guarded by itself. If
564 * something (rogue user app) forces this over
565 * MAX_DUP_SUPPRESSED_STACKS entries, the contents are cleared.
566 */
567 private final HashSet<Integer> mAlreadyLoggedViolatedStacks = new HashSet<Integer>();
568 private static final int MAX_DUP_SUPPRESSED_STACKS = 5000;
569
570 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -0700571 * Strict Mode background batched logging state.
572 *
573 * The string buffer is guarded by itself, and its lock is also
574 * used to determine if another batched write is already
575 * in-flight.
576 */
577 private final StringBuilder mStrictModeBuffer = new StringBuilder();
578
579 /**
Jeff Brown4d94a762010-09-23 11:33:28 -0700580 * True if we have a pending unexpired BROADCAST_TIMEOUT_MSG posted to our handler.
581 */
582 private boolean mPendingBroadcastTimeoutMessage;
583
584 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800585 * Intent broadcast that we have tried to start, but are
586 * waiting for its application's process to be created. We only
587 * need one (instead of a list) because we always process broadcasts
588 * one at a time, so no others can be started while waiting for this
589 * one.
590 */
591 BroadcastRecord mPendingBroadcast = null;
592
593 /**
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700594 * The receiver index that is pending, to restart the broadcast if needed.
595 */
596 int mPendingBroadcastRecvIndex;
597
598 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800599 * Keeps track of all IIntentReceivers that have been registered for
600 * broadcasts. Hash keys are the receiver IBinder, hash value is
601 * a ReceiverList.
602 */
603 final HashMap mRegisteredReceivers = new HashMap();
604
605 /**
606 * Resolver for broadcast intents to registered receivers.
607 * Holds BroadcastFilter (subclass of IntentFilter).
608 */
609 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
610 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
611 @Override
612 protected boolean allowFilterResult(
613 BroadcastFilter filter, List<BroadcastFilter> dest) {
614 IBinder target = filter.receiverList.receiver.asBinder();
615 for (int i=dest.size()-1; i>=0; i--) {
616 if (dest.get(i).receiverList.receiver.asBinder() == target) {
617 return false;
618 }
619 }
620 return true;
621 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -0700622
623 @Override
624 protected String packageForFilter(BroadcastFilter filter) {
625 return filter.packageName;
626 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800627 };
628
629 /**
630 * State of all active sticky broadcasts. Keys are the action of the
631 * sticky Intent, values are an ArrayList of all broadcasted intents with
632 * that action (which should usually be one).
633 */
634 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
635 new HashMap<String, ArrayList<Intent>>();
636
637 /**
638 * All currently running services.
639 */
640 final HashMap<ComponentName, ServiceRecord> mServices =
641 new HashMap<ComponentName, ServiceRecord>();
642
643 /**
644 * All currently running services indexed by the Intent used to start them.
645 */
646 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
647 new HashMap<Intent.FilterComparison, ServiceRecord>();
648
649 /**
650 * All currently bound service connections. Keys are the IBinder of
651 * the client's IServiceConnection.
652 */
Dianne Hackborn43d9ac82010-08-25 15:06:25 -0700653 final HashMap<IBinder, ArrayList<ConnectionRecord>> mServiceConnections
654 = new HashMap<IBinder, ArrayList<ConnectionRecord>>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800655
656 /**
657 * List of services that we have been asked to start,
658 * but haven't yet been able to. It is used to hold start requests
659 * while waiting for their corresponding application thread to get
660 * going.
661 */
662 final ArrayList<ServiceRecord> mPendingServices
663 = new ArrayList<ServiceRecord>();
664
665 /**
666 * List of services that are scheduled to restart following a crash.
667 */
668 final ArrayList<ServiceRecord> mRestartingServices
669 = new ArrayList<ServiceRecord>();
670
671 /**
672 * List of services that are in the process of being stopped.
673 */
674 final ArrayList<ServiceRecord> mStoppingServices
675 = new ArrayList<ServiceRecord>();
676
677 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700678 * Backup/restore process management
679 */
680 String mBackupAppName = null;
681 BackupRecord mBackupTarget = null;
682
683 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800684 * List of PendingThumbnailsRecord objects of clients who are still
685 * waiting to receive all of the thumbnails for a task.
686 */
687 final ArrayList mPendingThumbnails = new ArrayList();
688
689 /**
690 * List of HistoryRecord objects that have been finished and must
691 * still report back to a pending thumbnail receiver.
692 */
693 final ArrayList mCancelledThumbnails = new ArrayList();
694
695 /**
696 * All of the currently running global content providers. Keys are a
697 * string containing the provider name and values are a
698 * ContentProviderRecord object containing the data about it. Note
699 * that a single provider may be published under multiple names, so
700 * there may be multiple entries here for a single one in mProvidersByClass.
701 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700702 final HashMap<String, ContentProviderRecord> mProvidersByName
703 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800704
705 /**
706 * All of the currently running global content providers. Keys are a
707 * string containing the provider's implementation class and values are a
708 * ContentProviderRecord object containing the data about it.
709 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700710 final HashMap<String, ContentProviderRecord> mProvidersByClass
711 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800712
713 /**
714 * List of content providers who have clients waiting for them. The
715 * application is currently being launched and the provider will be
716 * removed from this list once it is published.
717 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700718 final ArrayList<ContentProviderRecord> mLaunchingProviders
719 = new ArrayList<ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800720
721 /**
722 * Global set of specific Uri permissions that have been granted.
723 */
724 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
725 = new SparseArray<HashMap<Uri, UriPermission>>();
726
Svetoslav Ganov54d068e2011-03-02 12:58:40 -0800727 CoreSettingsObserver mCoreSettingsObserver;
728
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800729 /**
730 * Thread-local storage used to carry caller permissions over through
731 * indirect content-provider access.
732 * @see #ActivityManagerService.openContentUri()
733 */
734 private class Identity {
735 public int pid;
736 public int uid;
737
738 Identity(int _pid, int _uid) {
739 pid = _pid;
740 uid = _uid;
741 }
742 }
743 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
744
745 /**
746 * All information we have collected about the runtime performance of
747 * any user id that can impact battery performance.
748 */
749 final BatteryStatsService mBatteryStatsService;
750
751 /**
752 * information about component usage
753 */
754 final UsageStatsService mUsageStatsService;
755
756 /**
757 * Current configuration information. HistoryRecord objects are given
758 * a reference to this object to indicate which configuration they are
759 * currently running in, so this object must be kept immutable.
760 */
761 Configuration mConfiguration = new Configuration();
762
763 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800764 * Current sequencing integer of the configuration, for skipping old
765 * configurations.
766 */
767 int mConfigurationSeq = 0;
768
769 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700770 * Hardware-reported OpenGLES version.
771 */
772 final int GL_ES_VERSION;
773
774 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800775 * List of initialization arguments to pass to all processes when binding applications to them.
776 * For example, references to the commonly used services.
777 */
778 HashMap<String, IBinder> mAppBindArgs;
779
780 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700781 * Temporary to avoid allocations. Protected by main lock.
782 */
783 final StringBuilder mStringBuilder = new StringBuilder(256);
784
785 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800786 * Used to control how we initialize the service.
787 */
788 boolean mStartRunning = false;
789 ComponentName mTopComponent;
790 String mTopAction;
791 String mTopData;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700792 boolean mProcessesReady = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800793 boolean mSystemReady = false;
794 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700795 boolean mWaitingUpdate = false;
796 boolean mDidUpdate = false;
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700797 boolean mOnBattery = false;
Dianne Hackborn0dad3642010-09-09 21:25:35 -0700798 boolean mLaunchWarningShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800799
800 Context mContext;
801
802 int mFactoryTest;
803
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700804 boolean mCheckedForSetup;
805
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800806 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700807 * The time at which we will allow normal application switches again,
808 * after a call to {@link #stopAppSwitches()}.
809 */
810 long mAppSwitchesAllowedTime;
811
812 /**
813 * This is set to true after the first switch after mAppSwitchesAllowedTime
814 * is set; any switches after that will clear the time.
815 */
816 boolean mDidAppSwitch;
817
818 /**
Dianne Hackborn287952c2010-09-22 22:34:31 -0700819 * Last time (in realtime) at which we checked for power usage.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700820 */
Dianne Hackborn287952c2010-09-22 22:34:31 -0700821 long mLastPowerCheckRealtime;
822
823 /**
824 * Last time (in uptime) at which we checked for power usage.
825 */
826 long mLastPowerCheckUptime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700827
828 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800829 * Set while we are wanting to sleep, to prevent any
830 * activities from being started/resumed.
831 */
832 boolean mSleeping = false;
833
834 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700835 * Set if we are shutting down the system, similar to sleeping.
836 */
837 boolean mShuttingDown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800838
839 /**
840 * Task identifier that activities are currently being started
841 * in. Incremented each time a new task is created.
842 * todo: Replace this with a TokenSpace class that generates non-repeating
843 * integers that won't wrap.
844 */
845 int mCurTask = 1;
846
847 /**
848 * Current sequence id for oom_adj computation traversal.
849 */
850 int mAdjSeq = 0;
851
852 /**
Dianne Hackborn906497c2010-05-10 15:57:38 -0700853 * Current sequence id for process LRU updating.
854 */
855 int mLruSeq = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800856
857 /**
858 * System monitoring: number of processes that died since the last
859 * N procs were started.
860 */
861 int[] mProcDeaths = new int[20];
862
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700863 /**
864 * This is set if we had to do a delayed dexopt of an app before launching
865 * it, to increasing the ANR timeouts in that case.
866 */
867 boolean mDidDexOpt;
868
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800869 String mDebugApp = null;
870 boolean mWaitForDebugger = false;
871 boolean mDebugTransient = false;
872 String mOrigDebugApp = null;
873 boolean mOrigWaitForDebugger = false;
874 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700875 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800876
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700877 final RemoteCallbackList<IActivityWatcher> mWatchers
878 = new RemoteCallbackList<IActivityWatcher>();
Jeff Sharkeya4620792011-05-20 15:29:23 -0700879
880 final RemoteCallbackList<IProcessObserver> mProcessObservers
881 = new RemoteCallbackList<IProcessObserver>();
882
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800883 /**
884 * Callback of last caller to {@link #requestPss}.
885 */
886 Runnable mRequestPssCallback;
887
888 /**
889 * Remaining processes for which we are waiting results from the last
890 * call to {@link #requestPss}.
891 */
892 final ArrayList<ProcessRecord> mRequestPssList
893 = new ArrayList<ProcessRecord>();
894
895 /**
896 * Runtime statistics collection thread. This object's lock is used to
897 * protect all related state.
898 */
899 final Thread mProcessStatsThread;
900
901 /**
902 * Used to collect process stats when showing not responding dialog.
903 * Protected by mProcessStatsThread.
904 */
905 final ProcessStats mProcessStats = new ProcessStats(
906 MONITOR_THREAD_CPU_USAGE);
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700907 final AtomicLong mLastCpuTime = new AtomicLong(0);
908 final AtomicBoolean mProcessStatsMutexFree = new AtomicBoolean(true);
909
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800910 long mLastWriteTime = 0;
911
912 /**
913 * Set to true after the system has finished booting.
914 */
915 boolean mBooted = false;
916
917 int mProcessLimit = 0;
918
919 WindowManagerService mWindowManager;
920
921 static ActivityManagerService mSelf;
922 static ActivityThread mSystemThread;
923
924 private final class AppDeathRecipient implements IBinder.DeathRecipient {
925 final ProcessRecord mApp;
926 final int mPid;
927 final IApplicationThread mAppThread;
928
929 AppDeathRecipient(ProcessRecord app, int pid,
930 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800931 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800932 TAG, "New death recipient " + this
933 + " for thread " + thread.asBinder());
934 mApp = app;
935 mPid = pid;
936 mAppThread = thread;
937 }
938
939 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800940 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800941 TAG, "Death received in " + this
942 + " for thread " + mAppThread.asBinder());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800943 synchronized(ActivityManagerService.this) {
944 appDiedLocked(mApp, mPid, mAppThread);
945 }
946 }
947 }
948
949 static final int SHOW_ERROR_MSG = 1;
950 static final int SHOW_NOT_RESPONDING_MSG = 2;
951 static final int SHOW_FACTORY_ERROR_MSG = 3;
952 static final int UPDATE_CONFIGURATION_MSG = 4;
953 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
954 static final int WAIT_FOR_DEBUGGER_MSG = 6;
955 static final int BROADCAST_INTENT_MSG = 7;
956 static final int BROADCAST_TIMEOUT_MSG = 8;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800957 static final int SERVICE_TIMEOUT_MSG = 12;
958 static final int UPDATE_TIME_ZONE = 13;
959 static final int SHOW_UID_ERROR_MSG = 14;
960 static final int IM_FEELING_LUCKY_MSG = 15;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800961 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700962 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -0700963 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800964 static final int FINALIZE_PENDING_INTENT_MSG = 23;
Dianne Hackborn860755f2010-06-03 18:47:52 -0700965 static final int POST_HEAVY_NOTIFICATION_MSG = 24;
966 static final int CANCEL_HEAVY_NOTIFICATION_MSG = 25;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700967 static final int SHOW_STRICT_MODE_VIOLATION_MSG = 26;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700968 static final int CHECK_EXCESSIVE_WAKE_LOCKS_MSG = 27;
Robert Greenwalt03595d02010-11-02 14:08:23 -0700969 static final int CLEAR_DNS_CACHE = 28;
Robert Greenwalt434203a2010-10-11 16:00:27 -0700970 static final int UPDATE_HTTP_PROXY = 29;
Dianne Hackborn36cd41f2011-05-25 21:00:46 -0700971 static final int SHOW_COMPAT_MODE_DIALOG_MSG = 30;
Dianne Hackborn36f80f32011-05-31 18:26:45 -0700972 static final int DISPATCH_FOREGROUND_ACTIVITIES_CHANGED = 31;
973 static final int DISPATCH_PROCESS_DIED = 32;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800974
975 AlertDialog mUidAlert;
Dianne Hackborn36cd41f2011-05-25 21:00:46 -0700976 CompatModeDialog mCompatModeDialog;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800977
978 final Handler mHandler = new Handler() {
979 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800980 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800981 //}
982
983 public void handleMessage(Message msg) {
984 switch (msg.what) {
985 case SHOW_ERROR_MSG: {
986 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800987 synchronized (ActivityManagerService.this) {
988 ProcessRecord proc = (ProcessRecord)data.get("app");
989 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800990 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800991 return;
992 }
993 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -0700994 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -0800995 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800996 d.show();
997 proc.crashDialog = d;
998 } else {
999 // The device is asleep, so just pretend that the user
1000 // saw a crash dialog and hit "force quit".
1001 res.set(0);
1002 }
1003 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001004
1005 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001006 } break;
1007 case SHOW_NOT_RESPONDING_MSG: {
1008 synchronized (ActivityManagerService.this) {
1009 HashMap data = (HashMap) msg.obj;
1010 ProcessRecord proc = (ProcessRecord)data.get("app");
1011 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001012 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001013 return;
1014 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001015
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001016 Intent intent = new Intent("android.intent.action.ANR");
1017 if (!mProcessesReady) {
1018 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
1019 }
1020 broadcastIntentLocked(null, null, intent,
The Android Open Source Project4df24232009-03-05 14:34:35 -08001021 null, null, 0, null, null, null,
1022 false, false, MY_PID, Process.SYSTEM_UID);
1023
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001024 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001025 mContext, proc, (ActivityRecord)data.get("activity"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001026 d.show();
1027 proc.anrDialog = d;
1028 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001029
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001030 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001031 } break;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001032 case SHOW_STRICT_MODE_VIOLATION_MSG: {
1033 HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
1034 synchronized (ActivityManagerService.this) {
1035 ProcessRecord proc = (ProcessRecord) data.get("app");
1036 if (proc == null) {
1037 Slog.e(TAG, "App not found when showing strict mode dialog.");
1038 break;
1039 }
1040 if (proc.crashDialog != null) {
1041 Slog.e(TAG, "App already has strict mode dialog: " + proc);
1042 return;
1043 }
1044 AppErrorResult res = (AppErrorResult) data.get("result");
1045 if (!mSleeping && !mShuttingDown) {
1046 Dialog d = new StrictModeViolationDialog(mContext, res, proc);
1047 d.show();
1048 proc.crashDialog = d;
1049 } else {
1050 // The device is asleep, so just pretend that the user
1051 // saw a crash dialog and hit "force quit".
1052 res.set(0);
1053 }
1054 }
1055 ensureBootCompleted();
1056 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001057 case SHOW_FACTORY_ERROR_MSG: {
1058 Dialog d = new FactoryErrorDialog(
1059 mContext, msg.getData().getCharSequence("msg"));
1060 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001061 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001062 } break;
1063 case UPDATE_CONFIGURATION_MSG: {
1064 final ContentResolver resolver = mContext.getContentResolver();
1065 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1066 } break;
1067 case GC_BACKGROUND_PROCESSES_MSG: {
1068 synchronized (ActivityManagerService.this) {
1069 performAppGcsIfAppropriateLocked();
1070 }
1071 } break;
1072 case WAIT_FOR_DEBUGGER_MSG: {
1073 synchronized (ActivityManagerService.this) {
1074 ProcessRecord app = (ProcessRecord)msg.obj;
1075 if (msg.arg1 != 0) {
1076 if (!app.waitedForDebugger) {
1077 Dialog d = new AppWaitingForDebuggerDialog(
1078 ActivityManagerService.this,
1079 mContext, app);
1080 app.waitDialog = d;
1081 app.waitedForDebugger = true;
1082 d.show();
1083 }
1084 } else {
1085 if (app.waitDialog != null) {
1086 app.waitDialog.dismiss();
1087 app.waitDialog = null;
1088 }
1089 }
1090 }
1091 } break;
1092 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001093 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001094 TAG, "Received BROADCAST_INTENT_MSG");
1095 processNextBroadcast(true);
1096 } break;
1097 case BROADCAST_TIMEOUT_MSG: {
Jeff Brown4d94a762010-09-23 11:33:28 -07001098 synchronized (ActivityManagerService.this) {
1099 broadcastTimeoutLocked(true);
Jeff Hamiltonacf84742010-05-25 22:10:18 -05001100 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001101 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001102 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001103 if (mDidDexOpt) {
1104 mDidDexOpt = false;
1105 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1106 nmsg.obj = msg.obj;
1107 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1108 return;
1109 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001110 serviceTimeout((ProcessRecord)msg.obj);
1111 } break;
1112 case UPDATE_TIME_ZONE: {
1113 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001114 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1115 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001116 if (r.thread != null) {
1117 try {
1118 r.thread.updateTimeZone();
1119 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001120 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001121 }
1122 }
1123 }
1124 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001125 } break;
Robert Greenwalt03595d02010-11-02 14:08:23 -07001126 case CLEAR_DNS_CACHE: {
1127 synchronized (ActivityManagerService.this) {
1128 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1129 ProcessRecord r = mLruProcesses.get(i);
1130 if (r.thread != null) {
1131 try {
1132 r.thread.clearDnsCache();
1133 } catch (RemoteException ex) {
1134 Slog.w(TAG, "Failed to clear dns cache for: " + r.info.processName);
1135 }
1136 }
1137 }
1138 }
1139 } break;
Robert Greenwalt434203a2010-10-11 16:00:27 -07001140 case UPDATE_HTTP_PROXY: {
1141 ProxyProperties proxy = (ProxyProperties)msg.obj;
1142 String host = "";
1143 String port = "";
1144 String exclList = "";
1145 if (proxy != null) {
1146 host = proxy.getHost();
1147 port = Integer.toString(proxy.getPort());
1148 exclList = proxy.getExclusionList();
1149 }
1150 synchronized (ActivityManagerService.this) {
1151 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1152 ProcessRecord r = mLruProcesses.get(i);
1153 if (r.thread != null) {
1154 try {
1155 r.thread.setHttpProxy(host, port, exclList);
1156 } catch (RemoteException ex) {
1157 Slog.w(TAG, "Failed to update http proxy for: " +
1158 r.info.processName);
1159 }
1160 }
1161 }
1162 }
1163 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001164 case SHOW_UID_ERROR_MSG: {
1165 // XXX This is a temporary dialog, no need to localize.
1166 AlertDialog d = new BaseErrorDialog(mContext);
1167 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1168 d.setCancelable(false);
1169 d.setTitle("System UIDs Inconsistent");
1170 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 +02001171 d.setButton(DialogInterface.BUTTON_POSITIVE, "I'm Feeling Lucky",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001172 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1173 mUidAlert = d;
1174 d.show();
1175 } break;
1176 case IM_FEELING_LUCKY_MSG: {
1177 if (mUidAlert != null) {
1178 mUidAlert.dismiss();
1179 mUidAlert = null;
1180 }
1181 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001182 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001183 if (mDidDexOpt) {
1184 mDidDexOpt = false;
1185 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1186 nmsg.obj = msg.obj;
1187 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1188 return;
1189 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001190 ProcessRecord app = (ProcessRecord)msg.obj;
1191 synchronized (ActivityManagerService.this) {
1192 processStartTimedOutLocked(app);
1193 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001194 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001195 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1196 synchronized (ActivityManagerService.this) {
1197 doPendingActivityLaunchesLocked(true);
1198 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001199 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001200 case KILL_APPLICATION_MSG: {
1201 synchronized (ActivityManagerService.this) {
1202 int uid = msg.arg1;
1203 boolean restart = (msg.arg2 == 1);
1204 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001205 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001206 }
1207 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001208 case FINALIZE_PENDING_INTENT_MSG: {
1209 ((PendingIntentRecord)msg.obj).completeFinalize();
1210 } break;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001211 case POST_HEAVY_NOTIFICATION_MSG: {
1212 INotificationManager inm = NotificationManager.getService();
1213 if (inm == null) {
1214 return;
1215 }
1216
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001217 ActivityRecord root = (ActivityRecord)msg.obj;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001218 ProcessRecord process = root.app;
1219 if (process == null) {
1220 return;
1221 }
1222
1223 try {
1224 Context context = mContext.createPackageContext(process.info.packageName, 0);
1225 String text = mContext.getString(R.string.heavy_weight_notification,
1226 context.getApplicationInfo().loadLabel(context.getPackageManager()));
1227 Notification notification = new Notification();
1228 notification.icon = com.android.internal.R.drawable.stat_sys_adb; //context.getApplicationInfo().icon;
1229 notification.when = 0;
1230 notification.flags = Notification.FLAG_ONGOING_EVENT;
1231 notification.tickerText = text;
1232 notification.defaults = 0; // please be quiet
1233 notification.sound = null;
1234 notification.vibrate = null;
1235 notification.setLatestEventInfo(context, text,
1236 mContext.getText(R.string.heavy_weight_notification_detail),
1237 PendingIntent.getActivity(mContext, 0, root.intent,
1238 PendingIntent.FLAG_CANCEL_CURRENT));
1239
1240 try {
1241 int[] outId = new int[1];
1242 inm.enqueueNotification("android", R.string.heavy_weight_notification,
1243 notification, outId);
1244 } catch (RuntimeException e) {
1245 Slog.w(ActivityManagerService.TAG,
1246 "Error showing notification for heavy-weight app", e);
1247 } catch (RemoteException e) {
1248 }
1249 } catch (NameNotFoundException e) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07001250 Slog.w(TAG, "Unable to create context for heavy notification", e);
Dianne Hackborn860755f2010-06-03 18:47:52 -07001251 }
1252 } break;
1253 case CANCEL_HEAVY_NOTIFICATION_MSG: {
1254 INotificationManager inm = NotificationManager.getService();
1255 if (inm == null) {
1256 return;
1257 }
1258 try {
1259 inm.cancelNotification("android",
1260 R.string.heavy_weight_notification);
1261 } catch (RuntimeException e) {
1262 Slog.w(ActivityManagerService.TAG,
1263 "Error canceling notification for service", e);
1264 } catch (RemoteException e) {
1265 }
1266 } break;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001267 case CHECK_EXCESSIVE_WAKE_LOCKS_MSG: {
1268 synchronized (ActivityManagerService.this) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001269 checkExcessivePowerUsageLocked(true);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -07001270 removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001271 Message nmsg = obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
1272 sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001273 }
1274 } break;
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07001275 case SHOW_COMPAT_MODE_DIALOG_MSG: {
1276 synchronized (ActivityManagerService.this) {
1277 ActivityRecord ar = (ActivityRecord)msg.obj;
1278 if (mCompatModeDialog != null) {
1279 if (mCompatModeDialog.mAppInfo.packageName.equals(
1280 ar.info.applicationInfo.packageName)) {
1281 return;
1282 }
1283 mCompatModeDialog.dismiss();
1284 mCompatModeDialog = null;
1285 }
Dianne Hackborn29478262011-06-07 15:44:22 -07001286 if (ar != null && false) {
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07001287 if (mCompatModePackages.getPackageAskCompatModeLocked(
1288 ar.packageName)) {
1289 int mode = mCompatModePackages.computeCompatModeLocked(
1290 ar.info.applicationInfo);
1291 if (mode == ActivityManager.COMPAT_MODE_DISABLED
1292 || mode == ActivityManager.COMPAT_MODE_ENABLED) {
1293 mCompatModeDialog = new CompatModeDialog(
1294 ActivityManagerService.this, mContext,
1295 ar.info.applicationInfo);
1296 mCompatModeDialog.show();
1297 }
1298 }
1299 }
1300 }
Dianne Hackborn36f80f32011-05-31 18:26:45 -07001301 break;
1302 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07001303 case DISPATCH_FOREGROUND_ACTIVITIES_CHANGED: {
Jeff Sharkey287bd832011-05-28 19:36:26 -07001304 final int pid = msg.arg1;
1305 final int uid = msg.arg2;
1306 final boolean foregroundActivities = (Boolean) msg.obj;
1307 dispatchForegroundActivitiesChanged(pid, uid, foregroundActivities);
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07001308 break;
1309 }
1310 case DISPATCH_PROCESS_DIED: {
Jeff Sharkey287bd832011-05-28 19:36:26 -07001311 final int pid = msg.arg1;
1312 final int uid = msg.arg2;
1313 dispatchProcessDied(pid, uid);
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07001314 break;
1315 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001316 }
1317 }
1318 };
1319
1320 public static void setSystemProcess() {
1321 try {
1322 ActivityManagerService m = mSelf;
1323
1324 ServiceManager.addService("activity", m);
1325 ServiceManager.addService("meminfo", new MemBinder(m));
Chet Haase9c1e23b2011-03-24 10:51:31 -07001326 ServiceManager.addService("gfxinfo", new GraphicsBinder(m));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001327 if (MONITOR_CPU_USAGE) {
1328 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1329 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001330 ServiceManager.addService("permission", new PermissionController(m));
1331
1332 ApplicationInfo info =
1333 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001334 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001335 mSystemThread.installSystemApplicationInfo(info);
1336
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001337 synchronized (mSelf) {
1338 ProcessRecord app = mSelf.newProcessRecordLocked(
1339 mSystemThread.getApplicationThread(), info,
1340 info.processName);
1341 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001342 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001343 app.maxAdj = SYSTEM_ADJ;
1344 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1345 synchronized (mSelf.mPidsSelfLocked) {
1346 mSelf.mPidsSelfLocked.put(app.pid, app);
1347 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001348 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001349 }
1350 } catch (PackageManager.NameNotFoundException e) {
1351 throw new RuntimeException(
1352 "Unable to find android system package", e);
1353 }
1354 }
1355
1356 public void setWindowManager(WindowManagerService wm) {
1357 mWindowManager = wm;
1358 }
1359
1360 public static final Context main(int factoryTest) {
1361 AThread thr = new AThread();
1362 thr.start();
1363
1364 synchronized (thr) {
1365 while (thr.mService == null) {
1366 try {
1367 thr.wait();
1368 } catch (InterruptedException e) {
1369 }
1370 }
1371 }
1372
1373 ActivityManagerService m = thr.mService;
1374 mSelf = m;
1375 ActivityThread at = ActivityThread.systemMain();
1376 mSystemThread = at;
1377 Context context = at.getSystemContext();
Dianne Hackborn247fe742011-01-08 17:25:57 -08001378 context.setTheme(android.R.style.Theme_Holo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001379 m.mContext = context;
1380 m.mFactoryTest = factoryTest;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001381 m.mMainStack = new ActivityStack(m, context, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001382
1383 m.mBatteryStatsService.publish(context);
1384 m.mUsageStatsService.publish(context);
1385
1386 synchronized (thr) {
1387 thr.mReady = true;
1388 thr.notifyAll();
1389 }
1390
1391 m.startRunning(null, null, null, null);
1392
1393 return context;
1394 }
1395
1396 public static ActivityManagerService self() {
1397 return mSelf;
1398 }
1399
1400 static class AThread extends Thread {
1401 ActivityManagerService mService;
1402 boolean mReady = false;
1403
1404 public AThread() {
1405 super("ActivityManager");
1406 }
1407
1408 public void run() {
1409 Looper.prepare();
1410
1411 android.os.Process.setThreadPriority(
1412 android.os.Process.THREAD_PRIORITY_FOREGROUND);
Christopher Tate160edb32010-06-30 17:46:30 -07001413 android.os.Process.setCanSelfBackground(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001414
1415 ActivityManagerService m = new ActivityManagerService();
1416
1417 synchronized (this) {
1418 mService = m;
1419 notifyAll();
1420 }
1421
1422 synchronized (this) {
1423 while (!mReady) {
1424 try {
1425 wait();
1426 } catch (InterruptedException e) {
1427 }
1428 }
1429 }
1430
Brad Fitzpatrickec062f62010-11-03 09:56:54 -07001431 // For debug builds, log event loop stalls to dropbox for analysis.
1432 if (StrictMode.conditionallyEnableDebugLogging()) {
1433 Slog.i(TAG, "Enabled StrictMode logging for AThread's Looper");
1434 }
1435
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001436 Looper.loop();
1437 }
1438 }
1439
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001440 static class MemBinder extends Binder {
1441 ActivityManagerService mActivityManagerService;
1442 MemBinder(ActivityManagerService activityManagerService) {
1443 mActivityManagerService = activityManagerService;
1444 }
1445
1446 @Override
1447 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07001448 mActivityManagerService.dumpApplicationMemoryUsage(fd, pw, " ", args);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001449 }
1450 }
1451
Chet Haase9c1e23b2011-03-24 10:51:31 -07001452 static class GraphicsBinder extends Binder {
1453 ActivityManagerService mActivityManagerService;
1454 GraphicsBinder(ActivityManagerService activityManagerService) {
1455 mActivityManagerService = activityManagerService;
1456 }
1457
1458 @Override
1459 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07001460 mActivityManagerService.dumpGraphicsHardwareUsage(fd, pw, args);
Chet Haase9c1e23b2011-03-24 10:51:31 -07001461 }
1462 }
1463
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001464 static class CpuBinder extends Binder {
1465 ActivityManagerService mActivityManagerService;
1466 CpuBinder(ActivityManagerService activityManagerService) {
1467 mActivityManagerService = activityManagerService;
1468 }
1469
1470 @Override
1471 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1472 synchronized (mActivityManagerService.mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07001473 pw.print(mActivityManagerService.mProcessStats.printCurrentLoad());
1474 pw.print(mActivityManagerService.mProcessStats.printCurrentState(
1475 SystemClock.uptimeMillis()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001476 }
1477 }
1478 }
1479
1480 private ActivityManagerService() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001481 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001482
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001483 File dataDir = Environment.getDataDirectory();
1484 File systemDir = new File(dataDir, "system");
1485 systemDir.mkdirs();
1486 mBatteryStatsService = new BatteryStatsService(new File(
1487 systemDir, "batterystats.bin").toString());
1488 mBatteryStatsService.getActiveStatistics().readLocked();
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001489 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
Dianne Hackborn287952c2010-09-22 22:34:31 -07001490 mOnBattery = DEBUG_POWER ? true
1491 : mBatteryStatsService.getActiveStatistics().getIsOnBattery();
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001492 mBatteryStatsService.getActiveStatistics().setCallback(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001493
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001494 mUsageStatsService = new UsageStatsService(new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001495 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001496
Jack Palevichb90d28c2009-07-22 15:35:24 -07001497 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1498 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1499
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001500 mConfiguration.setToDefaults();
1501 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001502 mProcessStats.init();
1503
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07001504 mCompatModePackages = new CompatModePackages(this, systemDir);
1505
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001506 // Add ourself to the Watchdog monitors.
1507 Watchdog.getInstance().addMonitor(this);
1508
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001509 mProcessStatsThread = new Thread("ProcessStats") {
1510 public void run() {
1511 while (true) {
1512 try {
1513 try {
1514 synchronized(this) {
1515 final long now = SystemClock.uptimeMillis();
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001516 long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001517 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001518 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001519 // + ", write delay=" + nextWriteDelay);
1520 if (nextWriteDelay < nextCpuDelay) {
1521 nextCpuDelay = nextWriteDelay;
1522 }
1523 if (nextCpuDelay > 0) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001524 mProcessStatsMutexFree.set(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001525 this.wait(nextCpuDelay);
1526 }
1527 }
1528 } catch (InterruptedException e) {
1529 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001530 updateCpuStatsNow();
1531 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001532 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001533 }
1534 }
1535 }
1536 };
1537 mProcessStatsThread.start();
1538 }
1539
1540 @Override
1541 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1542 throws RemoteException {
1543 try {
1544 return super.onTransact(code, data, reply, flags);
1545 } catch (RuntimeException e) {
1546 // The activity manager only throws security exceptions, so let's
1547 // log all others.
1548 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001549 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001550 }
1551 throw e;
1552 }
1553 }
1554
1555 void updateCpuStats() {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001556 final long now = SystemClock.uptimeMillis();
1557 if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
1558 return;
1559 }
1560 if (mProcessStatsMutexFree.compareAndSet(true, false)) {
1561 synchronized (mProcessStatsThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001562 mProcessStatsThread.notify();
1563 }
1564 }
1565 }
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001566
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001567 void updateCpuStatsNow() {
1568 synchronized (mProcessStatsThread) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001569 mProcessStatsMutexFree.set(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001570 final long now = SystemClock.uptimeMillis();
1571 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001572
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001573 if (MONITOR_CPU_USAGE &&
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001574 mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
1575 mLastCpuTime.set(now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001576 haveNewCpuStats = true;
1577 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001578 //Slog.i(TAG, mProcessStats.printCurrentState());
1579 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001580 // + mProcessStats.getTotalCpuPercent() + "%");
1581
Joe Onorato8a9b2202010-02-26 18:56:32 -08001582 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001583 if ("true".equals(SystemProperties.get("events.cpu"))) {
1584 int user = mProcessStats.getLastUserTime();
1585 int system = mProcessStats.getLastSystemTime();
1586 int iowait = mProcessStats.getLastIoWaitTime();
1587 int irq = mProcessStats.getLastIrqTime();
1588 int softIrq = mProcessStats.getLastSoftIrqTime();
1589 int idle = mProcessStats.getLastIdleTime();
1590
1591 int total = user + system + iowait + irq + softIrq + idle;
1592 if (total == 0) total = 1;
1593
Doug Zongker2bec3d42009-12-04 12:52:44 -08001594 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001595 ((user+system+iowait+irq+softIrq) * 100) / total,
1596 (user * 100) / total,
1597 (system * 100) / total,
1598 (iowait * 100) / total,
1599 (irq * 100) / total,
1600 (softIrq * 100) / total);
1601 }
1602 }
1603
Amith Yamasanie43530a2009-08-21 13:11:37 -07001604 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001605 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001606 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001607 synchronized(mPidsSelfLocked) {
1608 if (haveNewCpuStats) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001609 if (mOnBattery) {
1610 int perc = bstats.startAddingCpuLocked();
1611 int totalUTime = 0;
1612 int totalSTime = 0;
Dianne Hackborn287952c2010-09-22 22:34:31 -07001613 final int N = mProcessStats.countStats();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001614 for (int i=0; i<N; i++) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001615 ProcessStats.Stats st = mProcessStats.getStats(i);
1616 if (!st.working) {
1617 continue;
1618 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001619 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001620 int otherUTime = (st.rel_utime*perc)/100;
1621 int otherSTime = (st.rel_stime*perc)/100;
1622 totalUTime += otherUTime;
1623 totalSTime += otherSTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001624 if (pr != null) {
1625 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001626 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1627 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001628 ps.addSpeedStepTimes(cpuSpeedTimes);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001629 pr.curCpuTime += (st.rel_utime+st.rel_stime) * 10;
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001630 } else {
1631 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001632 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001633 if (ps != null) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001634 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1635 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001636 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001637 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001638 }
1639 }
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001640 bstats.finishAddingCpuLocked(perc, totalUTime,
1641 totalSTime, cpuSpeedTimes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001642 }
1643 }
1644 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001645
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001646 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1647 mLastWriteTime = now;
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001648 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001649 }
1650 }
1651 }
1652 }
1653
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001654 @Override
1655 public void batteryNeedsCpuUpdate() {
1656 updateCpuStatsNow();
1657 }
1658
1659 @Override
1660 public void batteryPowerChanged(boolean onBattery) {
1661 // When plugging in, update the CPU stats first before changing
1662 // the plug state.
1663 updateCpuStatsNow();
1664 synchronized (this) {
1665 synchronized(mPidsSelfLocked) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001666 mOnBattery = DEBUG_POWER ? true : onBattery;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001667 }
1668 }
1669 }
1670
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001671 /**
1672 * Initialize the application bind args. These are passed to each
1673 * process when the bindApplication() IPC is sent to the process. They're
1674 * lazily setup to make sure the services are running when they're asked for.
1675 */
1676 private HashMap<String, IBinder> getCommonServicesLocked() {
1677 if (mAppBindArgs == null) {
1678 mAppBindArgs = new HashMap<String, IBinder>();
1679
1680 // Setup the application init args
1681 mAppBindArgs.put("package", ServiceManager.getService("package"));
1682 mAppBindArgs.put("window", ServiceManager.getService("window"));
1683 mAppBindArgs.put(Context.ALARM_SERVICE,
1684 ServiceManager.getService(Context.ALARM_SERVICE));
1685 }
1686 return mAppBindArgs;
1687 }
1688
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001689 final void setFocusedActivityLocked(ActivityRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001690 if (mFocusedActivity != r) {
1691 mFocusedActivity = r;
1692 mWindowManager.setFocusedApp(r, true);
1693 }
1694 }
1695
Dianne Hackborn906497c2010-05-10 15:57:38 -07001696 private final void updateLruProcessInternalLocked(ProcessRecord app,
1697 boolean oomAdj, boolean updateActivityTime, int bestPos) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001698 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001699 int lrui = mLruProcesses.indexOf(app);
1700 if (lrui >= 0) mLruProcesses.remove(lrui);
1701
1702 int i = mLruProcesses.size()-1;
1703 int skipTop = 0;
1704
Dianne Hackborn906497c2010-05-10 15:57:38 -07001705 app.lruSeq = mLruSeq;
1706
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001707 // compute the new weight for this process.
1708 if (updateActivityTime) {
1709 app.lastActivityTime = SystemClock.uptimeMillis();
1710 }
1711 if (app.activities.size() > 0) {
1712 // If this process has activities, we more strongly want to keep
1713 // it around.
1714 app.lruWeight = app.lastActivityTime;
1715 } else if (app.pubProviders.size() > 0) {
1716 // If this process contains content providers, we want to keep
1717 // it a little more strongly.
1718 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1719 // Also don't let it kick out the first few "real" hidden processes.
1720 skipTop = MIN_HIDDEN_APPS;
1721 } else {
1722 // If this process doesn't have activities, we less strongly
1723 // want to keep it around, and generally want to avoid getting
1724 // in front of any very recently used activities.
1725 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1726 // Also don't let it kick out the first few "real" hidden processes.
1727 skipTop = MIN_HIDDEN_APPS;
1728 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001729
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001730 while (i >= 0) {
1731 ProcessRecord p = mLruProcesses.get(i);
1732 // If this app shouldn't be in front of the first N background
1733 // apps, then skip over that many that are currently hidden.
1734 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1735 skipTop--;
1736 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001737 if (p.lruWeight <= app.lruWeight || i < bestPos) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001738 mLruProcesses.add(i+1, app);
1739 break;
1740 }
1741 i--;
1742 }
1743 if (i < 0) {
1744 mLruProcesses.add(0, app);
1745 }
1746
Dianne Hackborn906497c2010-05-10 15:57:38 -07001747 // If the app is currently using a content provider or service,
1748 // bump those processes as well.
1749 if (app.connections.size() > 0) {
1750 for (ConnectionRecord cr : app.connections) {
1751 if (cr.binding != null && cr.binding.service != null
1752 && cr.binding.service.app != null
1753 && cr.binding.service.app.lruSeq != mLruSeq) {
1754 updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,
1755 updateActivityTime, i+1);
1756 }
1757 }
1758 }
1759 if (app.conProviders.size() > 0) {
1760 for (ContentProviderRecord cpr : app.conProviders.keySet()) {
1761 if (cpr.app != null && cpr.app.lruSeq != mLruSeq) {
1762 updateLruProcessInternalLocked(cpr.app, oomAdj,
1763 updateActivityTime, i+1);
1764 }
1765 }
1766 }
1767
Joe Onorato8a9b2202010-02-26 18:56:32 -08001768 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001769 if (oomAdj) {
1770 updateOomAdjLocked();
1771 }
1772 }
1773
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001774 final void updateLruProcessLocked(ProcessRecord app,
Dianne Hackborn906497c2010-05-10 15:57:38 -07001775 boolean oomAdj, boolean updateActivityTime) {
1776 mLruSeq++;
1777 updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
1778 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07001779
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001780 final ProcessRecord getProcessRecordLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001781 String processName, int uid) {
1782 if (uid == Process.SYSTEM_UID) {
1783 // The system gets to run in any process. If there are multiple
1784 // processes with the same uid, just pick the first (this
1785 // should never happen).
1786 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1787 processName);
1788 return procs != null ? procs.valueAt(0) : null;
1789 }
1790 ProcessRecord proc = mProcessNames.get(processName, uid);
1791 return proc;
1792 }
1793
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001794 void ensurePackageDexOpt(String packageName) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001795 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001796 try {
1797 if (pm.performDexOpt(packageName)) {
1798 mDidDexOpt = true;
1799 }
1800 } catch (RemoteException e) {
1801 }
1802 }
1803
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001804 boolean isNextTransitionForward() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001805 int transit = mWindowManager.getPendingAppTransition();
1806 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1807 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1808 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1809 }
1810
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001811 final ProcessRecord startProcessLocked(String processName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001812 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001813 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001814 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1815 // We don't have to do anything more if:
1816 // (1) There is an existing application record; and
1817 // (2) The caller doesn't think it is dead, OR there is no thread
1818 // object attached to it so we know it couldn't have crashed; and
1819 // (3) There is a pid assigned to it, so it is either starting or
1820 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001821 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001822 + " app=" + app + " knownToBeDead=" + knownToBeDead
1823 + " thread=" + (app != null ? app.thread : null)
1824 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01001825 if (app != null && app.pid > 0) {
1826 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001827 // We already have the app running, or are waiting for it to
1828 // come up (we have a pid but not yet its thread), so keep it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001829 if (DEBUG_PROCESSES) Slog.v(TAG, "App already running: " + app);
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001830 // If this is a new package in the process, add the package to the list
1831 app.addPackage(info.packageName);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001832 return app;
1833 } else {
1834 // An application record is attached to a previous process,
1835 // clean it up now.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001836 if (DEBUG_PROCESSES) Slog.v(TAG, "App died: " + app);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001837 handleAppDiedLocked(app, true);
1838 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001839 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01001840
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001841 String hostingNameStr = hostingName != null
1842 ? hostingName.flattenToShortString() : null;
1843
1844 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1845 // If we are in the background, then check to see if this process
1846 // is bad. If so, we will just silently fail.
1847 if (mBadProcesses.get(info.processName, info.uid) != null) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001848 if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid
1849 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001850 return null;
1851 }
1852 } else {
1853 // When the user is explicitly starting a process, then clear its
1854 // crash count so that we won't make it bad until they see at
1855 // least one crash dialog again, and make the process good again
1856 // if it had been bad.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001857 if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
1858 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001859 mProcessCrashTimes.remove(info.processName, info.uid);
1860 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001861 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001862 info.processName);
1863 mBadProcesses.remove(info.processName, info.uid);
1864 if (app != null) {
1865 app.bad = false;
1866 }
1867 }
1868 }
1869
1870 if (app == null) {
1871 app = newProcessRecordLocked(null, info, processName);
1872 mProcessNames.put(processName, info.uid, app);
1873 } else {
1874 // If this is a new package in the process, add the package to the list
1875 app.addPackage(info.packageName);
1876 }
1877
1878 // If the system is not ready yet, then hold off on starting this
1879 // process until it is.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001880 if (!mProcessesReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001881 && !isAllowedWhileBooting(info)
1882 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001883 if (!mProcessesOnHold.contains(app)) {
1884 mProcessesOnHold.add(app);
1885 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001886 if (DEBUG_PROCESSES) Slog.v(TAG, "System not ready, putting on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001887 return app;
1888 }
1889
1890 startProcessLocked(app, hostingType, hostingNameStr);
1891 return (app.pid != 0) ? app : null;
1892 }
1893
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001894 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1895 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1896 }
1897
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001898 private final void startProcessLocked(ProcessRecord app,
1899 String hostingType, String hostingNameStr) {
1900 if (app.pid > 0 && app.pid != MY_PID) {
1901 synchronized (mPidsSelfLocked) {
1902 mPidsSelfLocked.remove(app.pid);
1903 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1904 }
1905 app.pid = 0;
1906 }
1907
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001908 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
1909 "startProcessLocked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001910 mProcessesOnHold.remove(app);
1911
1912 updateCpuStats();
1913
1914 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1915 mProcDeaths[0] = 0;
1916
1917 try {
1918 int uid = app.info.uid;
1919 int[] gids = null;
1920 try {
1921 gids = mContext.getPackageManager().getPackageGids(
1922 app.info.packageName);
1923 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001924 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001925 }
1926 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1927 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1928 && mTopComponent != null
1929 && app.processName.equals(mTopComponent.getPackageName())) {
1930 uid = 0;
1931 }
1932 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1933 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1934 uid = 0;
1935 }
1936 }
1937 int debugFlags = 0;
1938 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1939 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
Elliott Hughesfa36aee2011-06-17 14:39:41 -07001940 // Also turn on CheckJNI for debuggable apps. It's quite
1941 // awkward to turn on otherwise.
1942 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001943 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08001944 // Run the app in safe mode if its manifest requests so or the
1945 // system is booted in safe mode.
1946 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
1947 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08001948 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1949 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001950 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1951 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1952 }
Elliott Hughesae07ecf2011-07-06 17:33:27 -07001953 if ("1".equals(SystemProperties.get("debug.jni.logging"))) {
1954 debugFlags |= Zygote.DEBUG_ENABLE_JNI_LOGGING;
1955 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001956 if ("1".equals(SystemProperties.get("debug.assert"))) {
1957 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1958 }
Jeff Brown3f9dd282011-07-08 20:02:19 -07001959
1960 // Start the process. It will either succeed and return a result containing
1961 // the PID of the new process, or else throw a RuntimeException.
1962 Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
Elliott Hughese1dfcb72011-07-08 11:08:07 -07001963 app.processName, uid, uid, gids, debugFlags,
1964 app.info.targetSdkVersion, null);
Jeff Brown3f9dd282011-07-08 20:02:19 -07001965
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001966 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
1967 synchronized (bs) {
1968 if (bs.isOnBattery()) {
1969 app.batteryStats.incStartsLocked();
1970 }
1971 }
1972
Jeff Brown3f9dd282011-07-08 20:02:19 -07001973 EventLog.writeEvent(EventLogTags.AM_PROC_START, startResult.pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001974 app.processName, hostingType,
1975 hostingNameStr != null ? hostingNameStr : "");
1976
1977 if (app.persistent) {
Jeff Brown3f9dd282011-07-08 20:02:19 -07001978 Watchdog.getInstance().processStarted(app.processName, startResult.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001979 }
1980
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001981 StringBuilder buf = mStringBuilder;
1982 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001983 buf.append("Start proc ");
1984 buf.append(app.processName);
1985 buf.append(" for ");
1986 buf.append(hostingType);
1987 if (hostingNameStr != null) {
1988 buf.append(" ");
1989 buf.append(hostingNameStr);
1990 }
1991 buf.append(": pid=");
Jeff Brown3f9dd282011-07-08 20:02:19 -07001992 buf.append(startResult.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001993 buf.append(" uid=");
1994 buf.append(uid);
1995 buf.append(" gids={");
1996 if (gids != null) {
1997 for (int gi=0; gi<gids.length; gi++) {
1998 if (gi != 0) buf.append(", ");
1999 buf.append(gids[gi]);
2000
2001 }
2002 }
2003 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08002004 Slog.i(TAG, buf.toString());
Jeff Brown3f9dd282011-07-08 20:02:19 -07002005 app.pid = startResult.pid;
2006 app.usingWrapper = startResult.usingWrapper;
2007 app.removed = false;
2008 synchronized (mPidsSelfLocked) {
2009 this.mPidsSelfLocked.put(startResult.pid, app);
2010 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
2011 msg.obj = app;
2012 mHandler.sendMessageDelayed(msg, startResult.usingWrapper
2013 ? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002014 }
2015 } catch (RuntimeException e) {
2016 // XXX do better error recovery.
2017 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002018 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002019 }
2020 }
2021
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002022 void updateUsageStats(ActivityRecord resumedComponent, boolean resumed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002023 if (resumed) {
2024 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
2025 } else {
2026 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
2027 }
2028 }
2029
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002030 boolean startHomeActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002031 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
2032 && mTopAction == null) {
2033 // We are running in factory test mode, but unable to find
2034 // the factory test app, so just sit around displaying the
2035 // error message and don't try to start anything.
2036 return false;
2037 }
2038 Intent intent = new Intent(
2039 mTopAction,
2040 mTopData != null ? Uri.parse(mTopData) : null);
2041 intent.setComponent(mTopComponent);
2042 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
2043 intent.addCategory(Intent.CATEGORY_HOME);
2044 }
2045 ActivityInfo aInfo =
2046 intent.resolveActivityInfo(mContext.getPackageManager(),
2047 STOCK_PM_FLAGS);
2048 if (aInfo != null) {
2049 intent.setComponent(new ComponentName(
2050 aInfo.applicationInfo.packageName, aInfo.name));
2051 // Don't do this if the home app is currently being
2052 // instrumented.
2053 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
2054 aInfo.applicationInfo.uid);
2055 if (app == null || app.instrumentationClass == null) {
2056 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002057 mMainStack.startActivityLocked(null, intent, null, null, 0, aInfo,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002058 null, null, 0, 0, 0, false, false, null);
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002059 }
2060 }
2061
2062
2063 return true;
2064 }
2065
2066 /**
2067 * Starts the "new version setup screen" if appropriate.
2068 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002069 void startSetupActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002070 // Only do this once per boot.
2071 if (mCheckedForSetup) {
2072 return;
2073 }
2074
2075 // We will show this screen if the current one is a different
2076 // version than the last one shown, and we are not running in
2077 // low-level factory test mode.
2078 final ContentResolver resolver = mContext.getContentResolver();
2079 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
2080 Settings.Secure.getInt(resolver,
2081 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
2082 mCheckedForSetup = true;
2083
2084 // See if we should be showing the platform update setup UI.
2085 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
2086 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
2087 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
2088
2089 // We don't allow third party apps to replace this.
2090 ResolveInfo ri = null;
2091 for (int i=0; ris != null && i<ris.size(); i++) {
2092 if ((ris.get(i).activityInfo.applicationInfo.flags
2093 & ApplicationInfo.FLAG_SYSTEM) != 0) {
2094 ri = ris.get(i);
2095 break;
2096 }
2097 }
2098
2099 if (ri != null) {
2100 String vers = ri.activityInfo.metaData != null
2101 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
2102 : null;
2103 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
2104 vers = ri.activityInfo.applicationInfo.metaData.getString(
2105 Intent.METADATA_SETUP_VERSION);
2106 }
2107 String lastVers = Settings.Secure.getString(
2108 resolver, Settings.Secure.LAST_SETUP_SHOWN);
2109 if (vers != null && !vers.equals(lastVers)) {
2110 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2111 intent.setComponent(new ComponentName(
2112 ri.activityInfo.packageName, ri.activityInfo.name));
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002113 mMainStack.startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002114 null, null, 0, 0, 0, false, false, null);
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002115 }
2116 }
2117 }
2118 }
2119
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002120 CompatibilityInfo compatibilityInfoForPackageLocked(ApplicationInfo ai) {
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002121 return mCompatModePackages.compatibilityInfoForPackageLocked(ai);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002122 }
2123
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002124 public int getFrontActivityScreenCompatMode() {
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002125 synchronized (this) {
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002126 return mCompatModePackages.getFrontActivityScreenCompatModeLocked();
2127 }
2128 }
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002129
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002130 public void setFrontActivityScreenCompatMode(int mode) {
2131 synchronized (this) {
2132 mCompatModePackages.setFrontActivityScreenCompatModeLocked(mode);
2133 }
2134 }
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002135
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002136 public int getPackageScreenCompatMode(String packageName) {
2137 synchronized (this) {
2138 return mCompatModePackages.getPackageScreenCompatModeLocked(packageName);
2139 }
2140 }
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002141
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002142 public void setPackageScreenCompatMode(String packageName, int mode) {
2143 synchronized (this) {
2144 mCompatModePackages.setPackageScreenCompatModeLocked(packageName, mode);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002145 }
2146 }
2147
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07002148 public boolean getPackageAskScreenCompat(String packageName) {
2149 synchronized (this) {
2150 return mCompatModePackages.getPackageAskCompatModeLocked(packageName);
2151 }
2152 }
2153
2154 public void setPackageAskScreenCompat(String packageName, boolean ask) {
2155 synchronized (this) {
2156 mCompatModePackages.setPackageAskCompatModeLocked(packageName, ask);
2157 }
2158 }
2159
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002160 void reportResumedActivityLocked(ActivityRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002161 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002162
2163 final int identHash = System.identityHashCode(r);
2164 updateUsageStats(r, true);
2165
2166 int i = mWatchers.beginBroadcast();
2167 while (i > 0) {
2168 i--;
2169 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2170 if (w != null) {
2171 try {
2172 w.activityResuming(identHash);
2173 } catch (RemoteException e) {
2174 }
2175 }
2176 }
2177 mWatchers.finishBroadcast();
2178 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002179
Jeff Sharkeya4620792011-05-20 15:29:23 -07002180 private void dispatchForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities) {
2181 int i = mProcessObservers.beginBroadcast();
2182 while (i > 0) {
2183 i--;
2184 final IProcessObserver observer = mProcessObservers.getBroadcastItem(i);
2185 if (observer != null) {
2186 try {
2187 observer.onForegroundActivitiesChanged(pid, uid, foregroundActivities);
2188 } catch (RemoteException e) {
2189 }
2190 }
2191 }
2192 mProcessObservers.finishBroadcast();
2193 }
2194
2195 private void dispatchProcessDied(int pid, int uid) {
2196 int i = mProcessObservers.beginBroadcast();
2197 while (i > 0) {
2198 i--;
2199 final IProcessObserver observer = mProcessObservers.getBroadcastItem(i);
2200 if (observer != null) {
2201 try {
2202 observer.onProcessDied(pid, uid);
2203 } catch (RemoteException e) {
2204 }
2205 }
2206 }
2207 mProcessObservers.finishBroadcast();
2208 }
2209
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002210 final void doPendingActivityLaunchesLocked(boolean doResume) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002211 final int N = mPendingActivityLaunches.size();
2212 if (N <= 0) {
2213 return;
2214 }
2215 for (int i=0; i<N; i++) {
2216 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002217 mMainStack.startActivityUncheckedLocked(pal.r, pal.sourceRecord,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002218 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
2219 doResume && i == (N-1));
2220 }
2221 mPendingActivityLaunches.clear();
2222 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002223
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002224 public final int startActivity(IApplicationThread caller,
2225 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2226 int grantedMode, IBinder resultTo,
2227 String resultWho, int requestCode, boolean onlyIfNeeded,
2228 boolean debug) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002229 return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002230 grantedUriPermissions, grantedMode, resultTo, resultWho,
2231 requestCode, onlyIfNeeded, debug, null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002232 }
2233
2234 public final WaitResult startActivityAndWait(IApplicationThread caller,
2235 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2236 int grantedMode, IBinder resultTo,
2237 String resultWho, int requestCode, boolean onlyIfNeeded,
2238 boolean debug) {
2239 WaitResult res = new WaitResult();
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002240 mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002241 grantedUriPermissions, grantedMode, resultTo, resultWho,
2242 requestCode, onlyIfNeeded, debug, res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002243 return res;
2244 }
2245
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002246 public final int startActivityWithConfig(IApplicationThread caller,
2247 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2248 int grantedMode, IBinder resultTo,
2249 String resultWho, int requestCode, boolean onlyIfNeeded,
2250 boolean debug, Configuration config) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002251 return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002252 grantedUriPermissions, grantedMode, resultTo, resultWho,
2253 requestCode, onlyIfNeeded, debug, null, config);
2254 }
2255
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002256 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002257 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002258 IBinder resultTo, String resultWho, int requestCode,
2259 int flagsMask, int flagsValues) {
2260 // Refuse possible leaked file descriptors
2261 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
2262 throw new IllegalArgumentException("File descriptors passed in Intent");
2263 }
2264
2265 IIntentSender sender = intent.getTarget();
2266 if (!(sender instanceof PendingIntentRecord)) {
2267 throw new IllegalArgumentException("Bad PendingIntent object");
2268 }
2269
2270 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002271
2272 synchronized (this) {
2273 // If this is coming from the currently resumed activity, it is
2274 // effectively saying that app switches are allowed at this point.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002275 if (mMainStack.mResumedActivity != null
2276 && mMainStack.mResumedActivity.info.applicationInfo.uid ==
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002277 Binder.getCallingUid()) {
2278 mAppSwitchesAllowedTime = 0;
2279 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002280 }
2281
Dianne Hackborn6c418d52011-06-29 14:05:33 -07002282 return pir.sendInner(0, fillInIntent, resolvedType, null,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002283 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
2284 }
2285
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002286 public boolean startNextMatchingActivity(IBinder callingActivity,
2287 Intent intent) {
2288 // Refuse possible leaked file descriptors
2289 if (intent != null && intent.hasFileDescriptors() == true) {
2290 throw new IllegalArgumentException("File descriptors passed in Intent");
2291 }
2292
2293 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002294 int index = mMainStack.indexOfTokenLocked(callingActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002295 if (index < 0) {
2296 return false;
2297 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002298 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002299 if (r.app == null || r.app.thread == null) {
2300 // The caller is not running... d'oh!
2301 return false;
2302 }
2303 intent = new Intent(intent);
2304 // The caller is not allowed to change the data.
2305 intent.setDataAndType(r.intent.getData(), r.intent.getType());
2306 // And we are resetting to find the next component...
2307 intent.setComponent(null);
2308
2309 ActivityInfo aInfo = null;
2310 try {
2311 List<ResolveInfo> resolves =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002312 AppGlobals.getPackageManager().queryIntentActivities(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002313 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002314 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002315
2316 // Look for the original activity in the list...
2317 final int N = resolves != null ? resolves.size() : 0;
2318 for (int i=0; i<N; i++) {
2319 ResolveInfo rInfo = resolves.get(i);
2320 if (rInfo.activityInfo.packageName.equals(r.packageName)
2321 && rInfo.activityInfo.name.equals(r.info.name)) {
2322 // We found the current one... the next matching is
2323 // after it.
2324 i++;
2325 if (i<N) {
2326 aInfo = resolves.get(i).activityInfo;
2327 }
2328 break;
2329 }
2330 }
2331 } catch (RemoteException e) {
2332 }
2333
2334 if (aInfo == null) {
2335 // Nobody who is next!
2336 return false;
2337 }
2338
2339 intent.setComponent(new ComponentName(
2340 aInfo.applicationInfo.packageName, aInfo.name));
2341 intent.setFlags(intent.getFlags()&~(
2342 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
2343 Intent.FLAG_ACTIVITY_CLEAR_TOP|
2344 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
2345 Intent.FLAG_ACTIVITY_NEW_TASK));
2346
2347 // Okay now we need to start the new activity, replacing the
2348 // currently running activity. This is a little tricky because
2349 // we want to start the new one as if the current one is finished,
2350 // but not finish the current one first so that there is no flicker.
2351 // And thus...
2352 final boolean wasFinishing = r.finishing;
2353 r.finishing = true;
2354
2355 // Propagate reply information over to the new activity.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002356 final ActivityRecord resultTo = r.resultTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002357 final String resultWho = r.resultWho;
2358 final int requestCode = r.requestCode;
2359 r.resultTo = null;
2360 if (resultTo != null) {
2361 resultTo.removeResultsLocked(r, resultWho, requestCode);
2362 }
2363
2364 final long origId = Binder.clearCallingIdentity();
2365 // XXX we are not dealing with propagating grantedUriPermissions...
2366 // those are not yet exposed to user code, so there is no need.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002367 int res = mMainStack.startActivityLocked(r.app.thread, intent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002368 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002369 requestCode, -1, r.launchedFromUid, false, false, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002370 Binder.restoreCallingIdentity(origId);
2371
2372 r.finishing = wasFinishing;
2373 if (res != START_SUCCESS) {
2374 return false;
2375 }
2376 return true;
2377 }
2378 }
2379
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002380 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002381 Intent intent, String resolvedType, IBinder resultTo,
2382 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002383
2384 // This is so super not safe, that only the system (or okay root)
2385 // can do it.
2386 final int callingUid = Binder.getCallingUid();
2387 if (callingUid != 0 && callingUid != Process.myUid()) {
2388 throw new SecurityException(
2389 "startActivityInPackage only available to the system");
2390 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002391
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002392 return mMainStack.startActivityMayWait(null, uid, intent, resolvedType,
2393 null, 0, resultTo, resultWho, requestCode, onlyIfNeeded, false, null, null);
2394 }
2395
2396 public final int startActivities(IApplicationThread caller,
2397 Intent[] intents, String[] resolvedTypes, IBinder resultTo) {
2398 return mMainStack.startActivities(caller, -1, intents, resolvedTypes, resultTo);
2399 }
2400
2401 public final int startActivitiesInPackage(int uid,
2402 Intent[] intents, String[] resolvedTypes, IBinder resultTo) {
2403
2404 // This is so super not safe, that only the system (or okay root)
2405 // can do it.
2406 final int callingUid = Binder.getCallingUid();
2407 if (callingUid != 0 && callingUid != Process.myUid()) {
2408 throw new SecurityException(
2409 "startActivityInPackage only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002410 }
2411
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002412 return mMainStack.startActivities(null, uid, intents, resolvedTypes, resultTo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002413 }
2414
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002415 final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002416 int N = mRecentTasks.size();
Dianne Hackborn7c0e75e2010-12-21 19:15:40 -08002417 // Quick case: check if the top-most recent task is the same.
2418 if (N > 0 && mRecentTasks.get(0) == task) {
2419 return;
2420 }
2421 // Remove any existing entries that are the same kind of task.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002422 for (int i=0; i<N; i++) {
2423 TaskRecord tr = mRecentTasks.get(i);
2424 if ((task.affinity != null && task.affinity.equals(tr.affinity))
2425 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
2426 mRecentTasks.remove(i);
2427 i--;
2428 N--;
2429 if (task.intent == null) {
2430 // If the new recent task we are adding is not fully
2431 // specified, then replace it with the existing recent task.
2432 task = tr;
2433 }
2434 }
2435 }
2436 if (N >= MAX_RECENT_TASKS) {
2437 mRecentTasks.remove(N-1);
2438 }
2439 mRecentTasks.add(0, task);
2440 }
2441
2442 public void setRequestedOrientation(IBinder token,
2443 int requestedOrientation) {
2444 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002445 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002446 if (index < 0) {
2447 return;
2448 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002449 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002450 final long origId = Binder.clearCallingIdentity();
2451 mWindowManager.setAppOrientation(r, requestedOrientation);
2452 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07002453 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002454 r.mayFreezeScreenLocked(r.app) ? r : null);
2455 if (config != null) {
2456 r.frozenBeforeDestroy = true;
2457 if (!updateConfigurationLocked(config, r)) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002458 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002459 }
2460 }
2461 Binder.restoreCallingIdentity(origId);
2462 }
2463 }
2464
2465 public int getRequestedOrientation(IBinder token) {
2466 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002467 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002468 if (index < 0) {
2469 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
2470 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002471 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002472 return mWindowManager.getAppOrientation(r);
2473 }
2474 }
2475
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002476 /**
2477 * This is the internal entry point for handling Activity.finish().
2478 *
2479 * @param token The Binder token referencing the Activity we want to finish.
2480 * @param resultCode Result code, if any, from this Activity.
2481 * @param resultData Result data (Intent), if any, from this Activity.
2482 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11002483 * @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 -08002484 */
2485 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
2486 // Refuse possible leaked file descriptors
2487 if (resultData != null && resultData.hasFileDescriptors() == true) {
2488 throw new IllegalArgumentException("File descriptors passed in Intent");
2489 }
2490
2491 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002492 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002493 // Find the first activity that is not finishing.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002494 ActivityRecord next = mMainStack.topRunningActivityLocked(token, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002495 if (next != null) {
2496 // ask watcher if this is allowed
2497 boolean resumeOK = true;
2498 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002499 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002500 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002501 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002502 }
2503
2504 if (!resumeOK) {
2505 return false;
2506 }
2507 }
2508 }
2509 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002510 boolean res = mMainStack.requestFinishActivityLocked(token, resultCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002511 resultData, "app-request");
2512 Binder.restoreCallingIdentity(origId);
2513 return res;
2514 }
2515 }
2516
Dianne Hackborn860755f2010-06-03 18:47:52 -07002517 public final void finishHeavyWeightApp() {
2518 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2519 != PackageManager.PERMISSION_GRANTED) {
2520 String msg = "Permission Denial: finishHeavyWeightApp() from pid="
2521 + Binder.getCallingPid()
2522 + ", uid=" + Binder.getCallingUid()
2523 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2524 Slog.w(TAG, msg);
2525 throw new SecurityException(msg);
2526 }
2527
2528 synchronized(this) {
2529 if (mHeavyWeightProcess == null) {
2530 return;
2531 }
2532
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002533 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>(
Dianne Hackborn860755f2010-06-03 18:47:52 -07002534 mHeavyWeightProcess.activities);
2535 for (int i=0; i<activities.size(); i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002536 ActivityRecord r = activities.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002537 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002538 int index = mMainStack.indexOfTokenLocked(r);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002539 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002540 mMainStack.finishActivityLocked(r, index, Activity.RESULT_CANCELED,
Dianne Hackborn860755f2010-06-03 18:47:52 -07002541 null, "finish-heavy");
2542 }
2543 }
2544 }
2545
2546 mHeavyWeightProcess = null;
2547 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
2548 }
2549 }
2550
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002551 public void crashApplication(int uid, int initialPid, String packageName,
2552 String message) {
2553 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2554 != PackageManager.PERMISSION_GRANTED) {
2555 String msg = "Permission Denial: crashApplication() from pid="
2556 + Binder.getCallingPid()
2557 + ", uid=" + Binder.getCallingUid()
2558 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2559 Slog.w(TAG, msg);
2560 throw new SecurityException(msg);
2561 }
2562
2563 synchronized(this) {
2564 ProcessRecord proc = null;
2565
2566 // Figure out which process to kill. We don't trust that initialPid
2567 // still has any relation to current pids, so must scan through the
2568 // list.
2569 synchronized (mPidsSelfLocked) {
2570 for (int i=0; i<mPidsSelfLocked.size(); i++) {
2571 ProcessRecord p = mPidsSelfLocked.valueAt(i);
2572 if (p.info.uid != uid) {
2573 continue;
2574 }
2575 if (p.pid == initialPid) {
2576 proc = p;
2577 break;
2578 }
2579 for (String str : p.pkgList) {
2580 if (str.equals(packageName)) {
2581 proc = p;
2582 }
2583 }
2584 }
2585 }
2586
2587 if (proc == null) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07002588 Slog.w(TAG, "crashApplication: nothing for uid=" + uid
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002589 + " initialPid=" + initialPid
2590 + " packageName=" + packageName);
2591 return;
2592 }
2593
2594 if (proc.thread != null) {
Dianne Hackborn9f531192010-08-04 17:48:03 -07002595 if (proc.pid == Process.myPid()) {
2596 Log.w(TAG, "crashApplication: trying to crash self!");
2597 return;
2598 }
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002599 long ident = Binder.clearCallingIdentity();
2600 try {
2601 proc.thread.scheduleCrash(message);
2602 } catch (RemoteException e) {
2603 }
2604 Binder.restoreCallingIdentity(ident);
2605 }
2606 }
2607 }
2608
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002609 public final void finishSubActivity(IBinder token, String resultWho,
2610 int requestCode) {
2611 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002612 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002613 if (index < 0) {
2614 return;
2615 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002616 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002617
2618 final long origId = Binder.clearCallingIdentity();
2619
2620 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002621 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2622 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002623 if (r.resultTo == self && r.requestCode == requestCode) {
2624 if ((r.resultWho == null && resultWho == null) ||
2625 (r.resultWho != null && r.resultWho.equals(resultWho))) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002626 mMainStack.finishActivityLocked(r, i,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002627 Activity.RESULT_CANCELED, null, "request-sub");
2628 }
2629 }
2630 }
2631
2632 Binder.restoreCallingIdentity(origId);
2633 }
2634 }
2635
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002636 public boolean willActivityBeVisible(IBinder token) {
2637 synchronized(this) {
2638 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002639 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2640 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002641 if (r == token) {
2642 return true;
2643 }
2644 if (r.fullscreen && !r.finishing) {
2645 return false;
2646 }
2647 }
2648 return true;
2649 }
2650 }
2651
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002652 public void overridePendingTransition(IBinder token, String packageName,
2653 int enterAnim, int exitAnim) {
2654 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002655 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002656 if (index < 0) {
2657 return;
2658 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002659 ActivityRecord self = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002660
2661 final long origId = Binder.clearCallingIdentity();
2662
2663 if (self.state == ActivityState.RESUMED
2664 || self.state == ActivityState.PAUSING) {
2665 mWindowManager.overridePendingAppTransition(packageName,
2666 enterAnim, exitAnim);
2667 }
2668
2669 Binder.restoreCallingIdentity(origId);
2670 }
2671 }
2672
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002673 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002674 * Main function for removing an existing process from the activity manager
2675 * as a result of that process going away. Clears out all connections
2676 * to the process.
2677 */
2678 private final void handleAppDiedLocked(ProcessRecord app,
2679 boolean restarting) {
2680 cleanUpApplicationRecordLocked(app, restarting, -1);
2681 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002682 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002683 }
2684
2685 // Just in case...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002686 if (mMainStack.mPausingActivity != null && mMainStack.mPausingActivity.app == app) {
2687 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " +mMainStack.mPausingActivity);
2688 mMainStack.mPausingActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002689 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002690 if (mMainStack.mLastPausedActivity != null && mMainStack.mLastPausedActivity.app == app) {
2691 mMainStack.mLastPausedActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002692 }
2693
2694 // Remove this application's activities from active lists.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002695 mMainStack.removeHistoryRecordsForAppLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002696
2697 boolean atTop = true;
2698 boolean hasVisibleActivities = false;
2699
2700 // Clean out the history list.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002701 int i = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002702 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002703 TAG, "Removing app " + app + " from history with " + i + " entries");
2704 while (i > 0) {
2705 i--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002706 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002707 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002708 TAG, "Record #" + i + " " + r + ": app=" + r.app);
2709 if (r.app == app) {
2710 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002711 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002712 TAG, "Removing this entry! frozen=" + r.haveState
2713 + " finishing=" + r.finishing);
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -08002714 r.makeFinishing();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002715 mMainStack.mHistory.remove(i);
Dianne Hackbornf26fd992011-04-08 18:14:09 -07002716 r.takeFromHistory();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002717 mWindowManager.removeAppToken(r);
2718 if (VALIDATE_TOKENS) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002719 mWindowManager.validateAppTokens(mMainStack.mHistory);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002720 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002721 r.removeUriPermissionsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002722
2723 } else {
2724 // We have the current state for this activity, so
2725 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002726 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002727 TAG, "Keeping entry, setting app to null");
2728 if (r.visible) {
2729 hasVisibleActivities = true;
2730 }
2731 r.app = null;
2732 r.nowVisible = false;
2733 if (!r.haveState) {
2734 r.icicle = null;
2735 }
2736 }
2737
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002738 r.stack.cleanUpActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002739 r.state = ActivityState.STOPPED;
2740 }
2741 atTop = false;
2742 }
2743
2744 app.activities.clear();
2745
2746 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002747 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002748 + " running instrumentation " + app.instrumentationClass);
2749 Bundle info = new Bundle();
2750 info.putString("shortMsg", "Process crashed.");
2751 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
2752 }
2753
2754 if (!restarting) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002755 if (!mMainStack.resumeTopActivityLocked(null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002756 // If there was nothing to resume, and we are not already
2757 // restarting this process, but there is a visible activity that
2758 // is hosted by the process... then make sure all visible
2759 // activities are running, taking care of restarting this
2760 // process.
2761 if (hasVisibleActivities) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002762 mMainStack.ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002763 }
2764 }
2765 }
2766 }
2767
2768 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
2769 IBinder threadBinder = thread.asBinder();
2770
2771 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002772 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2773 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002774 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
2775 return i;
2776 }
2777 }
2778 return -1;
2779 }
2780
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002781 final ProcessRecord getRecordForAppLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002782 IApplicationThread thread) {
2783 if (thread == null) {
2784 return null;
2785 }
2786
2787 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002788 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002789 }
2790
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002791 final void appDiedLocked(ProcessRecord app, int pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002792 IApplicationThread thread) {
2793
2794 mProcDeaths[0]++;
2795
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07002796 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
2797 synchronized (stats) {
2798 stats.noteProcessDiedLocked(app.info.uid, pid);
2799 }
2800
Magnus Edlund7bb25812010-02-24 15:45:06 +01002801 // Clean up already done if the process has been re-started.
2802 if (app.pid == pid && app.thread != null &&
2803 app.thread.asBinder() == thread.asBinder()) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07002804 if (!app.killedBackground) {
2805 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
2806 + ") has died.");
2807 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08002808 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002809 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002810 TAG, "Dying app: " + app + ", pid: " + pid
2811 + ", thread: " + thread.asBinder());
2812 boolean doLowMem = app.instrumentationClass == null;
2813 handleAppDiedLocked(app, false);
2814
2815 if (doLowMem) {
2816 // If there are no longer any background processes running,
2817 // and the app that died was not running instrumentation,
2818 // then tell everyone we are now low on memory.
2819 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002820 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2821 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002822 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
2823 haveBg = true;
2824 break;
2825 }
2826 }
2827
2828 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002829 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002830 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002831 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002832 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2833 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07002834 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002835 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
2836 // The low memory report is overriding any current
2837 // state for a GC request. Make sure to do
Dianne Hackborn32907cf2010-06-10 17:50:20 -07002838 // heavy/important/visible/foreground processes first.
2839 if (rec.setAdj <= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002840 rec.lastRequestedGc = 0;
2841 } else {
2842 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002843 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002844 rec.reportLowMemory = true;
2845 rec.lastLowMemory = now;
2846 mProcessesToGc.remove(rec);
2847 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002848 }
2849 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002850 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002851 }
2852 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01002853 } else if (app.pid != pid) {
2854 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002855 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01002856 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08002857 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002858 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002859 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002860 + thread.asBinder());
2861 }
2862 }
2863
Dan Egnor42471dd2010-01-07 17:25:22 -08002864 /**
2865 * If a stack trace dump file is configured, dump process stack traces.
Christopher Tate6ee412d2010-05-28 12:01:56 -07002866 * @param clearTraces causes the dump file to be erased prior to the new
2867 * traces being written, if true; when false, the new traces will be
2868 * appended to any existing file content.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002869 * @param firstPids of dalvik VM processes to dump stack traces for first
2870 * @param lastPids of dalvik VM processes to dump stack traces for last
Dan Egnor42471dd2010-01-07 17:25:22 -08002871 * @return file containing stack traces, or null if no dump file is configured
2872 */
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002873 public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> firstPids,
2874 ProcessStats processStats, SparseArray<Boolean> lastPids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002875 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
2876 if (tracesPath == null || tracesPath.length() == 0) {
2877 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002878 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002879
2880 File tracesFile = new File(tracesPath);
2881 try {
2882 File tracesDir = tracesFile.getParentFile();
2883 if (!tracesDir.exists()) tracesFile.mkdirs();
2884 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
2885
Christopher Tate6ee412d2010-05-28 12:01:56 -07002886 if (clearTraces && tracesFile.exists()) tracesFile.delete();
Dan Egnor42471dd2010-01-07 17:25:22 -08002887 tracesFile.createNewFile();
2888 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
2889 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002890 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08002891 return null;
2892 }
2893
2894 // Use a FileObserver to detect when traces finish writing.
2895 // The order of traces is considered important to maintain for legibility.
2896 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
2897 public synchronized void onEvent(int event, String path) { notify(); }
2898 };
2899
2900 try {
2901 observer.startWatching();
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002902
2903 // First collect all of the stacks of the most important pids.
2904 try {
2905 int num = firstPids.size();
2906 for (int i = 0; i < num; i++) {
2907 synchronized (observer) {
2908 Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT);
2909 observer.wait(200); // Wait for write-close, give up after 200msec
2910 }
2911 }
2912 } catch (InterruptedException e) {
2913 Log.wtf(TAG, e);
2914 }
2915
2916 // Next measure CPU usage.
2917 if (processStats != null) {
2918 processStats.init();
2919 System.gc();
2920 processStats.update();
2921 try {
2922 synchronized (processStats) {
2923 processStats.wait(500); // measure over 1/2 second.
2924 }
2925 } catch (InterruptedException e) {
2926 }
2927 processStats.update();
2928
2929 // We'll take the stack crawls of just the top apps using CPU.
2930 final int N = processStats.countWorkingStats();
2931 int numProcs = 0;
2932 for (int i=0; i<N && numProcs<5; i++) {
2933 ProcessStats.Stats stats = processStats.getWorkingStats(i);
2934 if (lastPids.indexOfKey(stats.pid) >= 0) {
2935 numProcs++;
2936 try {
2937 synchronized (observer) {
2938 Process.sendSignal(stats.pid, Process.SIGNAL_QUIT);
2939 observer.wait(200); // Wait for write-close, give up after 200msec
2940 }
2941 } catch (InterruptedException e) {
2942 Log.wtf(TAG, e);
2943 }
2944
2945 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002946 }
2947 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002948
2949 return tracesFile;
2950
Dan Egnor42471dd2010-01-07 17:25:22 -08002951 } finally {
2952 observer.stopWatching();
2953 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002954 }
2955
Jeff Brown4d94a762010-09-23 11:33:28 -07002956 private final class AppNotResponding implements Runnable {
2957 private final ProcessRecord mApp;
2958 private final String mAnnotation;
2959
2960 public AppNotResponding(ProcessRecord app, String annotation) {
2961 mApp = app;
2962 mAnnotation = annotation;
2963 }
2964
2965 @Override
2966 public void run() {
2967 appNotResponding(mApp, null, null, mAnnotation);
2968 }
2969 }
2970
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002971 final void appNotResponding(ProcessRecord app, ActivityRecord activity,
2972 ActivityRecord parent, final String annotation) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002973 ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
2974 SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20);
2975
Dianne Hackborn287952c2010-09-22 22:34:31 -07002976 if (mController != null) {
2977 try {
2978 // 0 == continue, -1 = kill process immediately
2979 int res = mController.appEarlyNotResponding(app.processName, app.pid, annotation);
2980 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2981 } catch (RemoteException e) {
2982 mController = null;
2983 }
2984 }
2985
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002986 long anrTime = SystemClock.uptimeMillis();
2987 if (MONITOR_CPU_USAGE) {
2988 updateCpuStatsNow();
2989 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002990
2991 synchronized (this) {
2992 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
2993 if (mShuttingDown) {
2994 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
2995 return;
2996 } else if (app.notResponding) {
2997 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
2998 return;
2999 } else if (app.crashing) {
3000 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
3001 return;
3002 }
3003
3004 // In case we come through here for the same app before completing
3005 // this one, mark as anring now so we will bail out.
3006 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08003007
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003008 // Log the ANR to the event log.
3009 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
3010 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08003011
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003012 // Dump thread traces as quickly as we can, starting with "interesting" processes.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003013 firstPids.add(app.pid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003014
3015 int parentPid = app.pid;
3016 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003017 if (parentPid != app.pid) firstPids.add(parentPid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003018
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003019 if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08003020
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003021 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
3022 ProcessRecord r = mLruProcesses.get(i);
3023 if (r != null && r.thread != null) {
3024 int pid = r.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003025 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
3026 if (r.persistent) {
3027 firstPids.add(pid);
3028 } else {
3029 lastPids.put(pid, Boolean.TRUE);
3030 }
3031 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003032 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003033 }
3034 }
3035
Dan Egnor42471dd2010-01-07 17:25:22 -08003036 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07003037 StringBuilder info = mStringBuilder;
3038 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08003039 info.append("ANR in ").append(app.processName);
3040 if (activity != null && activity.shortComponentName != null) {
3041 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07003042 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08003043 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003044 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08003045 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003046 }
Dan Egnor42471dd2010-01-07 17:25:22 -08003047 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08003048 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003049 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003050
Dianne Hackborn287952c2010-09-22 22:34:31 -07003051 final ProcessStats processStats = new ProcessStats(true);
3052
3053 File tracesFile = dumpStackTraces(true, firstPids, processStats, lastPids);
3054
Dan Egnor42471dd2010-01-07 17:25:22 -08003055 String cpuInfo = null;
3056 if (MONITOR_CPU_USAGE) {
3057 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003058 synchronized (mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003059 cpuInfo = mProcessStats.printCurrentState(anrTime);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003060 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003061 info.append(processStats.printCurrentLoad());
Dan Egnor42471dd2010-01-07 17:25:22 -08003062 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003063 }
3064
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003065 info.append(processStats.printCurrentState(anrTime));
3066
Joe Onorato8a9b2202010-02-26 18:56:32 -08003067 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08003068 if (tracesFile == null) {
3069 // There is no trace file, so dump (only) the alleged culprit's threads to the log
3070 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
3071 }
3072
3073 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
3074
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003075 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003076 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08003077 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
3078 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003079 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08003080 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
3081 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003082 }
3083 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003084 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003085 }
3086 }
3087
Dan Egnor42471dd2010-01-07 17:25:22 -08003088 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
3089 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
3090 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003091
3092 synchronized (this) {
3093 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07003094 Slog.w(TAG, "Killing " + app + ": background ANR");
3095 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
3096 app.processName, app.setAdj, "background ANR");
3097 Process.killProcessQuiet(app.pid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003098 return;
3099 }
3100
3101 // Set the app's notResponding state, and look up the errorReportReceiver
3102 makeAppNotRespondingLocked(app,
3103 activity != null ? activity.shortComponentName : null,
3104 annotation != null ? "ANR " + annotation : "ANR",
3105 info.toString());
3106
3107 // Bring up the infamous App Not Responding dialog
3108 Message msg = Message.obtain();
3109 HashMap map = new HashMap();
3110 msg.what = SHOW_NOT_RESPONDING_MSG;
3111 msg.obj = map;
3112 map.put("app", app);
3113 if (activity != null) {
3114 map.put("activity", activity);
3115 }
3116
3117 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08003118 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003119 }
3120
Dianne Hackborn0dad3642010-09-09 21:25:35 -07003121 final void showLaunchWarningLocked(final ActivityRecord cur, final ActivityRecord next) {
3122 if (!mLaunchWarningShown) {
3123 mLaunchWarningShown = true;
3124 mHandler.post(new Runnable() {
3125 @Override
3126 public void run() {
3127 synchronized (ActivityManagerService.this) {
3128 final Dialog d = new LaunchWarningWindow(mContext, cur, next);
3129 d.show();
3130 mHandler.postDelayed(new Runnable() {
3131 @Override
3132 public void run() {
3133 synchronized (ActivityManagerService.this) {
3134 d.dismiss();
3135 mLaunchWarningShown = false;
3136 }
3137 }
3138 }, 4000);
3139 }
3140 }
3141 });
3142 }
3143 }
3144
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003145 public boolean clearApplicationUserData(final String packageName,
3146 final IPackageDataObserver observer) {
3147 int uid = Binder.getCallingUid();
3148 int pid = Binder.getCallingPid();
3149 long callingId = Binder.clearCallingIdentity();
3150 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003151 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003152 int pkgUid = -1;
3153 synchronized(this) {
3154 try {
3155 pkgUid = pm.getPackageUid(packageName);
3156 } catch (RemoteException e) {
3157 }
3158 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003159 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003160 return false;
3161 }
3162 if (uid == pkgUid || checkComponentPermission(
3163 android.Manifest.permission.CLEAR_APP_USER_DATA,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08003164 pid, uid, -1, true)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003165 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003166 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003167 } else {
3168 throw new SecurityException(pid+" does not have permission:"+
3169 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
3170 "for process:"+packageName);
3171 }
3172 }
3173
3174 try {
3175 //clear application user data
3176 pm.clearApplicationUserData(packageName, observer);
3177 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
3178 Uri.fromParts("package", packageName, null));
3179 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003180 broadcastIntentInPackage("android", Process.SYSTEM_UID, intent,
3181 null, null, 0, null, null, null, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003182 } catch (RemoteException e) {
3183 }
3184 } finally {
3185 Binder.restoreCallingIdentity(callingId);
3186 }
3187 return true;
3188 }
3189
Dianne Hackborn03abb812010-01-04 18:43:19 -08003190 public void killBackgroundProcesses(final String packageName) {
3191 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
3192 != PackageManager.PERMISSION_GRANTED &&
3193 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
3194 != PackageManager.PERMISSION_GRANTED) {
3195 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003196 + Binder.getCallingPid()
3197 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08003198 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003199 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003200 throw new SecurityException(msg);
3201 }
3202
3203 long callingId = Binder.clearCallingIdentity();
3204 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003205 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003206 int pkgUid = -1;
3207 synchronized(this) {
3208 try {
3209 pkgUid = pm.getPackageUid(packageName);
3210 } catch (RemoteException e) {
3211 }
3212 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003213 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003214 return;
3215 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003216 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003217 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003218 }
3219 } finally {
3220 Binder.restoreCallingIdentity(callingId);
3221 }
3222 }
3223
3224 public void forceStopPackage(final String packageName) {
3225 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
3226 != PackageManager.PERMISSION_GRANTED) {
3227 String msg = "Permission Denial: forceStopPackage() from pid="
3228 + Binder.getCallingPid()
3229 + ", uid=" + Binder.getCallingUid()
3230 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003231 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003232 throw new SecurityException(msg);
3233 }
3234
3235 long callingId = Binder.clearCallingIdentity();
3236 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003237 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn03abb812010-01-04 18:43:19 -08003238 int pkgUid = -1;
3239 synchronized(this) {
3240 try {
3241 pkgUid = pm.getPackageUid(packageName);
3242 } catch (RemoteException e) {
3243 }
3244 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003245 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003246 return;
3247 }
3248 forceStopPackageLocked(packageName, pkgUid);
Dianne Hackborne7f97212011-02-24 14:40:20 -08003249 try {
3250 pm.setPackageStoppedState(packageName, true);
3251 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08003252 } catch (IllegalArgumentException e) {
3253 Slog.w(TAG, "Failed trying to unstop package "
3254 + packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08003255 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003256 }
3257 } finally {
3258 Binder.restoreCallingIdentity(callingId);
3259 }
3260 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003261
3262 /*
3263 * The pkg name and uid have to be specified.
3264 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
3265 */
3266 public void killApplicationWithUid(String pkg, int uid) {
3267 if (pkg == null) {
3268 return;
3269 }
3270 // Make sure the uid is valid.
3271 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003272 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003273 return;
3274 }
3275 int callerUid = Binder.getCallingUid();
3276 // Only the system server can kill an application
3277 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07003278 // Post an aysnc message to kill the application
3279 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
3280 msg.arg1 = uid;
3281 msg.arg2 = 0;
3282 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07003283 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003284 } else {
3285 throw new SecurityException(callerUid + " cannot kill pkg: " +
3286 pkg);
3287 }
3288 }
3289
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003290 public void closeSystemDialogs(String reason) {
3291 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003292 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003293 if (reason != null) {
3294 intent.putExtra("reason", reason);
3295 }
3296
3297 final int uid = Binder.getCallingUid();
3298 final long origId = Binder.clearCallingIdentity();
3299 synchronized (this) {
3300 int i = mWatchers.beginBroadcast();
3301 while (i > 0) {
3302 i--;
3303 IActivityWatcher w = mWatchers.getBroadcastItem(i);
3304 if (w != null) {
3305 try {
3306 w.closingSystemDialogs(reason);
3307 } catch (RemoteException e) {
3308 }
3309 }
3310 }
3311 mWatchers.finishBroadcast();
3312
Dianne Hackbornffa42482009-09-23 22:20:11 -07003313 mWindowManager.closeSystemDialogs(reason);
3314
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003315 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3316 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackbornffa42482009-09-23 22:20:11 -07003317 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003318 r.stack.finishActivityLocked(r, i,
Dianne Hackbornffa42482009-09-23 22:20:11 -07003319 Activity.RESULT_CANCELED, null, "close-sys");
3320 }
3321 }
3322
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003323 broadcastIntentLocked(null, null, intent, null,
3324 null, 0, null, null, null, false, false, -1, uid);
3325 }
3326 Binder.restoreCallingIdentity(origId);
3327 }
3328
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003329 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003330 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003331 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
3332 for (int i=pids.length-1; i>=0; i--) {
3333 infos[i] = new Debug.MemoryInfo();
3334 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003335 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003336 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003337 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07003338
3339 public void killApplicationProcess(String processName, int uid) {
3340 if (processName == null) {
3341 return;
3342 }
3343
3344 int callerUid = Binder.getCallingUid();
3345 // Only the system server can kill an application
3346 if (callerUid == Process.SYSTEM_UID) {
3347 synchronized (this) {
3348 ProcessRecord app = getProcessRecordLocked(processName, uid);
Christopher Tate4a627c72011-04-01 14:43:32 -07003349 if (app != null && app.thread != null) {
Christopher Tate5e1ab332009-09-01 20:32:49 -07003350 try {
3351 app.thread.scheduleSuicide();
3352 } catch (RemoteException e) {
3353 // If the other end already died, then our work here is done.
3354 }
3355 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003356 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07003357 + processName + " / " + uid);
3358 }
3359 }
3360 } else {
3361 throw new SecurityException(callerUid + " cannot kill app process: " +
3362 processName);
3363 }
3364 }
3365
Dianne Hackborn03abb812010-01-04 18:43:19 -08003366 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003367 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003368 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
3369 Uri.fromParts("package", packageName, null));
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003370 if (!mProcessesReady) {
3371 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
3372 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003373 intent.putExtra(Intent.EXTRA_UID, uid);
3374 broadcastIntentLocked(null, null, intent,
3375 null, null, 0, null, null, null,
3376 false, false, MY_PID, Process.SYSTEM_UID);
3377 }
3378
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003379 private final boolean killPackageProcessesLocked(String packageName, int uid,
3380 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003381 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003382
Dianne Hackborn03abb812010-01-04 18:43:19 -08003383 // Remove all processes this package may have touched: all with the
3384 // same UID (except for the system or root user), and all whose name
3385 // matches the package name.
3386 final String procNamePrefix = packageName + ":";
3387 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
3388 final int NA = apps.size();
3389 for (int ia=0; ia<NA; ia++) {
3390 ProcessRecord app = apps.valueAt(ia);
3391 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003392 if (doit) {
3393 procs.add(app);
3394 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003395 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
3396 || app.processName.equals(packageName)
3397 || app.processName.startsWith(procNamePrefix)) {
3398 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003399 if (!doit) {
3400 return true;
3401 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003402 app.removed = true;
3403 procs.add(app);
3404 }
3405 }
3406 }
3407 }
3408
3409 int N = procs.size();
3410 for (int i=0; i<N; i++) {
3411 removeProcessLocked(procs.get(i), callerWillRestart);
3412 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003413 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08003414 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003415
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003416 private final boolean forceStopPackageLocked(String name, int uid,
3417 boolean callerWillRestart, boolean purgeCache, boolean doit) {
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07003418 int i;
3419 int N;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003420
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003421 if (uid < 0) {
3422 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003423 uid = AppGlobals.getPackageManager().getPackageUid(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003424 } catch (RemoteException e) {
3425 }
3426 }
3427
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003428 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003429 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003430
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003431 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
3432 while (badApps.hasNext()) {
3433 SparseArray<Long> ba = badApps.next();
3434 if (ba.get(uid) != null) {
3435 badApps.remove();
3436 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003437 }
3438 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003439
3440 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
3441 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003442
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003443 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3444 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003445 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003446 if (!doit) {
3447 return true;
3448 }
3449 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003450 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003451 if (r.app != null) {
3452 r.app.removed = true;
3453 }
3454 r.app = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003455 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003456 }
3457 }
3458
3459 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
3460 for (ServiceRecord service : mServices.values()) {
3461 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003462 if (!doit) {
3463 return true;
3464 }
3465 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003466 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003467 if (service.app != null) {
3468 service.app.removed = true;
3469 }
3470 service.app = null;
3471 services.add(service);
3472 }
3473 }
3474
3475 N = services.size();
3476 for (i=0; i<N; i++) {
3477 bringDownServiceLocked(services.get(i), true);
3478 }
3479
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003480 if (doit) {
3481 if (purgeCache) {
3482 AttributeCache ac = AttributeCache.instance();
3483 if (ac != null) {
3484 ac.removePackage(name);
3485 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003486 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003487 mMainStack.resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003488 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003489
3490 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003491 }
3492
3493 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
3494 final String name = app.processName;
3495 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003496 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003497 TAG, "Force removing process " + app + " (" + name
3498 + "/" + uid + ")");
3499
3500 mProcessNames.remove(name, uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003501 if (mHeavyWeightProcess == app) {
3502 mHeavyWeightProcess = null;
3503 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3504 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003505 boolean needRestart = false;
3506 if (app.pid > 0 && app.pid != MY_PID) {
3507 int pid = app.pid;
3508 synchronized (mPidsSelfLocked) {
3509 mPidsSelfLocked.remove(pid);
3510 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3511 }
3512 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003513 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003514 Process.killProcess(pid);
3515
3516 if (app.persistent) {
3517 if (!callerWillRestart) {
3518 addAppLocked(app.info);
3519 } else {
3520 needRestart = true;
3521 }
3522 }
3523 } else {
3524 mRemovedProcesses.add(app);
3525 }
3526
3527 return needRestart;
3528 }
3529
3530 private final void processStartTimedOutLocked(ProcessRecord app) {
3531 final int pid = app.pid;
3532 boolean gone = false;
3533 synchronized (mPidsSelfLocked) {
3534 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
3535 if (knownApp != null && knownApp.thread == null) {
3536 mPidsSelfLocked.remove(pid);
3537 gone = true;
3538 }
3539 }
3540
3541 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003542 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003543 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003544 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003545 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003546 if (mHeavyWeightProcess == app) {
3547 mHeavyWeightProcess = null;
3548 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3549 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003550 // Take care of any launching providers waiting for this process.
3551 checkAppInLaunchingProvidersLocked(app, true);
3552 // Take care of any services that are waiting for the process.
3553 for (int i=0; i<mPendingServices.size(); i++) {
3554 ServiceRecord sr = mPendingServices.get(i);
3555 if (app.info.uid == sr.appInfo.uid
3556 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003557 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003558 mPendingServices.remove(i);
3559 i--;
3560 bringDownServiceLocked(sr, true);
3561 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003562 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07003563 EventLog.writeEvent(EventLogTags.AM_KILL, pid,
3564 app.processName, app.setAdj, "start timeout");
3565 Process.killProcessQuiet(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07003566 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003567 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07003568 try {
3569 IBackupManager bm = IBackupManager.Stub.asInterface(
3570 ServiceManager.getService(Context.BACKUP_SERVICE));
3571 bm.agentDisconnected(app.info.packageName);
3572 } catch (RemoteException e) {
3573 // Can't happen; the backup manager is local
3574 }
3575 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003576 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003577 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003578 mPendingBroadcast.state = BroadcastRecord.IDLE;
3579 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003580 mPendingBroadcast = null;
3581 scheduleBroadcastsLocked();
3582 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003583 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003584 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003585 }
3586 }
3587
3588 private final boolean attachApplicationLocked(IApplicationThread thread,
3589 int pid) {
3590
3591 // Find the application record that is being attached... either via
3592 // the pid if we are running in multiple processes, or just pull the
3593 // next app record if we are emulating process with anonymous threads.
3594 ProcessRecord app;
3595 if (pid != MY_PID && pid >= 0) {
3596 synchronized (mPidsSelfLocked) {
3597 app = mPidsSelfLocked.get(pid);
3598 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003599 } else {
3600 app = null;
3601 }
3602
3603 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003604 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003605 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003606 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003607 if (pid > 0 && pid != MY_PID) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07003608 Process.killProcessQuiet(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003609 } else {
3610 try {
3611 thread.scheduleExit();
3612 } catch (Exception e) {
3613 // Ignore exceptions.
3614 }
3615 }
3616 return false;
3617 }
3618
3619 // If this application record is still attached to a previous
3620 // process, clean it up now.
3621 if (app.thread != null) {
3622 handleAppDiedLocked(app, true);
3623 }
3624
3625 // Tell the process all about itself.
3626
Joe Onorato8a9b2202010-02-26 18:56:32 -08003627 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003628 TAG, "Binding process pid " + pid + " to record " + app);
3629
3630 String processName = app.processName;
3631 try {
3632 thread.asBinder().linkToDeath(new AppDeathRecipient(
3633 app, pid, thread), 0);
3634 } catch (RemoteException e) {
3635 app.resetPackageList();
3636 startProcessLocked(app, "link fail", processName);
3637 return false;
3638 }
3639
Doug Zongker2bec3d42009-12-04 12:52:44 -08003640 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003641
3642 app.thread = thread;
3643 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08003644 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
3645 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003646 app.forcingToForeground = null;
3647 app.foregroundServices = false;
3648 app.debugging = false;
3649
3650 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3651
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003652 boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003653 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003654
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003655 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003656 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003657 }
3658
Joe Onorato8a9b2202010-02-26 18:56:32 -08003659 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003660 TAG, "New app record " + app
3661 + " thread=" + thread.asBinder() + " pid=" + pid);
3662 try {
3663 int testMode = IApplicationThread.DEBUG_OFF;
3664 if (mDebugApp != null && mDebugApp.equals(processName)) {
3665 testMode = mWaitForDebugger
3666 ? IApplicationThread.DEBUG_WAIT
3667 : IApplicationThread.DEBUG_ON;
3668 app.debugging = true;
3669 if (mDebugTransient) {
3670 mDebugApp = mOrigDebugApp;
3671 mWaitForDebugger = mOrigWaitForDebugger;
3672 }
3673 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003674
Christopher Tate181fafa2009-05-14 11:12:14 -07003675 // If the app is being launched for restore or full backup, set it up specially
3676 boolean isRestrictedBackupMode = false;
3677 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
3678 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
Christopher Tate75a99702011-05-18 16:28:19 -07003679 || (mBackupTarget.backupMode == BackupRecord.RESTORE_FULL)
Christopher Tate181fafa2009-05-14 11:12:14 -07003680 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
3681 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003682
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07003683 ensurePackageDexOpt(app.instrumentationInfo != null
3684 ? app.instrumentationInfo.packageName
3685 : app.info.packageName);
3686 if (app.instrumentationClass != null) {
3687 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003688 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003689 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003690 + processName + " with config " + mConfiguration);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04003691 ApplicationInfo appInfo = app.instrumentationInfo != null
3692 ? app.instrumentationInfo : app.info;
Dianne Hackborn8ea5e1d2011-05-27 16:45:31 -07003693 app.compat = compatibilityInfoForPackageLocked(appInfo);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04003694 thread.bindApplication(processName, appInfo, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003695 app.instrumentationClass, app.instrumentationProfileFile,
3696 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003697 isRestrictedBackupMode || !normalMode,
Dianne Hackborn8ea5e1d2011-05-27 16:45:31 -07003698 mConfiguration, app.compat, getCommonServicesLocked(),
Svetoslav Ganov54d068e2011-03-02 12:58:40 -08003699 mCoreSettingsObserver.getCoreSettingsLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003700 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003701 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003702 } catch (Exception e) {
3703 // todo: Yikes! What should we do? For now we will try to
3704 // start another process, but that could easily get us in
3705 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08003706 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003707
3708 app.resetPackageList();
3709 startProcessLocked(app, "bind fail", processName);
3710 return false;
3711 }
3712
3713 // Remove this record from the list of starting applications.
3714 mPersistentStartingProcesses.remove(app);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003715 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
3716 "Attach application locked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003717 mProcessesOnHold.remove(app);
3718
3719 boolean badApp = false;
3720 boolean didSomething = false;
3721
3722 // See if the top visible activity is waiting to run in this process...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003723 ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07003724 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003725 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
3726 && processName.equals(hr.processName)) {
3727 try {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003728 if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003729 didSomething = true;
3730 }
3731 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003732 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003733 + hr.intent.getComponent().flattenToShortString(), e);
3734 badApp = true;
3735 }
3736 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003737 mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003738 }
3739 }
3740
3741 // Find any services that should be running in this process...
3742 if (!badApp && mPendingServices.size() > 0) {
3743 ServiceRecord sr = null;
3744 try {
3745 for (int i=0; i<mPendingServices.size(); i++) {
3746 sr = mPendingServices.get(i);
3747 if (app.info.uid != sr.appInfo.uid
3748 || !processName.equals(sr.processName)) {
3749 continue;
3750 }
3751
3752 mPendingServices.remove(i);
3753 i--;
3754 realStartServiceLocked(sr, app);
3755 didSomething = true;
3756 }
3757 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003758 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003759 + sr.shortName, e);
3760 badApp = true;
3761 }
3762 }
3763
3764 // Check if the next broadcast receiver is in this process...
3765 BroadcastRecord br = mPendingBroadcast;
3766 if (!badApp && br != null && br.curApp == app) {
3767 try {
3768 mPendingBroadcast = null;
3769 processCurBroadcastLocked(br, app);
3770 didSomething = true;
3771 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003772 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003773 + br.curComponent.flattenToShortString(), e);
3774 badApp = true;
Jeff Brown4d94a762010-09-23 11:33:28 -07003775 logBroadcastReceiverDiscardLocked(br);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003776 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
3777 br.resultExtras, br.resultAbort, true);
3778 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01003779 // We need to reset the state if we fails to start the receiver.
3780 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003781 }
3782 }
3783
Christopher Tate181fafa2009-05-14 11:12:14 -07003784 // Check whether the next backup agent is in this process...
3785 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003786 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003787 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07003788 try {
Dianne Hackborne2515ee2011-04-27 18:52:56 -04003789 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo,
3790 compatibilityInfoForPackageLocked(mBackupTarget.appInfo),
3791 mBackupTarget.backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -07003792 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003793 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07003794 e.printStackTrace();
3795 }
3796 }
3797
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003798 if (badApp) {
3799 // todo: Also need to kill application to deal with all
3800 // kinds of exceptions.
3801 handleAppDiedLocked(app, false);
3802 return false;
3803 }
3804
3805 if (!didSomething) {
3806 updateOomAdjLocked();
3807 }
3808
3809 return true;
3810 }
3811
3812 public final void attachApplication(IApplicationThread thread) {
3813 synchronized (this) {
3814 int callingPid = Binder.getCallingPid();
3815 final long origId = Binder.clearCallingIdentity();
3816 attachApplicationLocked(thread, callingPid);
3817 Binder.restoreCallingIdentity(origId);
3818 }
3819 }
3820
Dianne Hackborne88846e2009-09-30 21:34:25 -07003821 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003822 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003823 mMainStack.activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003824 Binder.restoreCallingIdentity(origId);
3825 }
3826
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003827 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003828 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003829 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003830 mWindowManager.enableScreenAfterBoot();
3831 }
3832
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003833 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003834 IntentFilter pkgFilter = new IntentFilter();
3835 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
3836 pkgFilter.addDataScheme("package");
3837 mContext.registerReceiver(new BroadcastReceiver() {
3838 @Override
3839 public void onReceive(Context context, Intent intent) {
3840 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
3841 if (pkgs != null) {
3842 for (String pkg : pkgs) {
Vairavan Srinivasan61f07652010-07-22 13:36:40 -07003843 synchronized (ActivityManagerService.this) {
3844 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
3845 setResultCode(Activity.RESULT_OK);
3846 return;
3847 }
3848 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003849 }
3850 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003851 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003852 }, pkgFilter);
3853
3854 synchronized (this) {
3855 // Ensure that any processes we had put on hold are now started
3856 // up.
3857 final int NP = mProcessesOnHold.size();
3858 if (NP > 0) {
3859 ArrayList<ProcessRecord> procs =
3860 new ArrayList<ProcessRecord>(mProcessesOnHold);
3861 for (int ip=0; ip<NP; ip++) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003862 if (DEBUG_PROCESSES) Slog.v(TAG, "Starting process on hold: "
3863 + procs.get(ip));
3864 startProcessLocked(procs.get(ip), "on-hold", null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003865 }
3866 }
3867
3868 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07003869 // Start looking for apps that are abusing wake locks.
3870 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07003871 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003872 // Tell anyone interested that we are done booting!
Dianne Hackbornf4c454b2010-08-11 12:47:41 -07003873 SystemProperties.set("sys.boot_completed", "1");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003874 broadcastIntentLocked(null, null,
3875 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
3876 null, null, 0, null, null,
3877 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
3878 false, false, MY_PID, Process.SYSTEM_UID);
3879 }
3880 }
3881 }
3882
3883 final void ensureBootCompleted() {
3884 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003885 boolean enableScreen;
3886 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003887 booting = mBooting;
3888 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003889 enableScreen = !mBooted;
3890 mBooted = true;
3891 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003892
3893 if (booting) {
3894 finishBooting();
3895 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003896
3897 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003898 enableScreenAfterBoot();
3899 }
3900 }
3901
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08003902 public final void activityPaused(IBinder token) {
3903 final long origId = Binder.clearCallingIdentity();
3904 mMainStack.activityPaused(token, false);
3905 Binder.restoreCallingIdentity(origId);
3906 }
3907
3908 public final void activityStopped(IBinder token, Bundle icicle, Bitmap thumbnail,
3909 CharSequence description) {
3910 if (localLOGV) Slog.v(
3911 TAG, "Activity stopped: token=" + token);
3912
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003913 // Refuse possible leaked file descriptors
3914 if (icicle != null && icicle.hasFileDescriptors()) {
3915 throw new IllegalArgumentException("File descriptors passed in Bundle");
3916 }
3917
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003918 ActivityRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003919
3920 final long origId = Binder.clearCallingIdentity();
3921
3922 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003923 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003924 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003925 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08003926 r.icicle = icicle;
3927 r.haveState = true;
Dianne Hackbornf26fd992011-04-08 18:14:09 -07003928 r.updateThumbnail(thumbnail, description);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003929 r.stopped = true;
3930 r.state = ActivityState.STOPPED;
3931 if (!r.finishing) {
3932 if (r.configDestroy) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003933 r.stack.destroyActivityLocked(r, true);
3934 r.stack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003935 }
3936 }
3937 }
3938 }
3939
3940 if (r != null) {
3941 sendPendingThumbnail(r, null, null, null, false);
3942 }
3943
3944 trimApplications();
3945
3946 Binder.restoreCallingIdentity(origId);
3947 }
3948
3949 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003950 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003951 mMainStack.activityDestroyed(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003952 }
3953
3954 public String getCallingPackage(IBinder token) {
3955 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003956 ActivityRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07003957 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003958 }
3959 }
3960
3961 public ComponentName getCallingActivity(IBinder token) {
3962 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003963 ActivityRecord r = getCallingRecordLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003964 return r != null ? r.intent.getComponent() : null;
3965 }
3966 }
3967
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003968 private ActivityRecord getCallingRecordLocked(IBinder token) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003969 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003970 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003971 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003972 if (r != null) {
3973 return r.resultTo;
3974 }
3975 }
3976 return null;
3977 }
3978
3979 public ComponentName getActivityClassForToken(IBinder token) {
3980 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003981 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003982 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003983 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003984 return r.intent.getComponent();
3985 }
3986 return null;
3987 }
3988 }
3989
3990 public String getPackageForToken(IBinder token) {
3991 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003992 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003993 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003994 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003995 return r.packageName;
3996 }
3997 return null;
3998 }
3999 }
4000
4001 public IIntentSender getIntentSender(int type,
4002 String packageName, IBinder token, String resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004003 int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004004 // Refuse possible leaked file descriptors
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004005 if (intents != null) {
4006 if (intents.length < 1) {
4007 throw new IllegalArgumentException("Intents array length must be >= 1");
4008 }
4009 for (int i=0; i<intents.length; i++) {
4010 Intent intent = intents[i];
Dianne Hackborn52b0ce02011-04-14 13:09:32 -07004011 if (intent != null) {
4012 if (intent.hasFileDescriptors()) {
4013 throw new IllegalArgumentException("File descriptors passed in Intent");
4014 }
4015 if (type == INTENT_SENDER_BROADCAST &&
4016 (intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
4017 throw new IllegalArgumentException(
4018 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
4019 }
4020 intents[i] = new Intent(intent);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004021 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004022 }
4023 if (resolvedTypes != null && resolvedTypes.length != intents.length) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07004024 throw new IllegalArgumentException(
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004025 "Intent array length does not match resolvedTypes length");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07004026 }
4027 }
4028
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004029 synchronized(this) {
4030 int callingUid = Binder.getCallingUid();
4031 try {
Jeff Brown10e89712011-07-08 18:52:57 -07004032 if (callingUid != 0 && callingUid != Process.SYSTEM_UID) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004033 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004034 .getPackageUid(packageName);
4035 if (uid != Binder.getCallingUid()) {
4036 String msg = "Permission Denial: getIntentSender() from pid="
4037 + Binder.getCallingPid()
4038 + ", uid=" + Binder.getCallingUid()
4039 + ", (need uid=" + uid + ")"
4040 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004041 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004042 throw new SecurityException(msg);
4043 }
4044 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004045
4046 return getIntentSenderLocked(type, packageName, callingUid,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004047 token, resultWho, requestCode, intents, resolvedTypes, flags);
Dianne Hackborn860755f2010-06-03 18:47:52 -07004048
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004049 } catch (RemoteException e) {
4050 throw new SecurityException(e);
4051 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004052 }
4053 }
4054
4055 IIntentSender getIntentSenderLocked(int type,
4056 String packageName, int callingUid, IBinder token, String resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004057 int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004058 ActivityRecord activity = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004059 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004060 int index = mMainStack.indexOfTokenLocked(token);
Dianne Hackborn860755f2010-06-03 18:47:52 -07004061 if (index < 0) {
4062 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004063 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004064 activity = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackborn860755f2010-06-03 18:47:52 -07004065 if (activity.finishing) {
4066 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004067 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004068 }
4069
4070 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
4071 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
4072 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
4073 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
4074 |PendingIntent.FLAG_UPDATE_CURRENT);
4075
4076 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
4077 type, packageName, activity, resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004078 requestCode, intents, resolvedTypes, flags);
Dianne Hackborn860755f2010-06-03 18:47:52 -07004079 WeakReference<PendingIntentRecord> ref;
4080 ref = mIntentSenderRecords.get(key);
4081 PendingIntentRecord rec = ref != null ? ref.get() : null;
4082 if (rec != null) {
4083 if (!cancelCurrent) {
4084 if (updateCurrent) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004085 if (rec.key.requestIntent != null) {
4086 rec.key.requestIntent.replaceExtras(intents != null ? intents[0] : null);
4087 }
4088 if (intents != null) {
4089 intents[intents.length-1] = rec.key.requestIntent;
4090 rec.key.allIntents = intents;
4091 rec.key.allResolvedTypes = resolvedTypes;
4092 } else {
4093 rec.key.allIntents = null;
4094 rec.key.allResolvedTypes = null;
4095 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004096 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004097 return rec;
4098 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004099 rec.canceled = true;
4100 mIntentSenderRecords.remove(key);
4101 }
4102 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004103 return rec;
4104 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004105 rec = new PendingIntentRecord(this, key, callingUid);
4106 mIntentSenderRecords.put(key, rec.ref);
4107 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
4108 if (activity.pendingResults == null) {
4109 activity.pendingResults
4110 = new HashSet<WeakReference<PendingIntentRecord>>();
4111 }
4112 activity.pendingResults.add(rec.ref);
4113 }
4114 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004115 }
4116
4117 public void cancelIntentSender(IIntentSender sender) {
4118 if (!(sender instanceof PendingIntentRecord)) {
4119 return;
4120 }
4121 synchronized(this) {
4122 PendingIntentRecord rec = (PendingIntentRecord)sender;
4123 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004124 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004125 .getPackageUid(rec.key.packageName);
4126 if (uid != Binder.getCallingUid()) {
4127 String msg = "Permission Denial: cancelIntentSender() from pid="
4128 + Binder.getCallingPid()
4129 + ", uid=" + Binder.getCallingUid()
4130 + " is not allowed to cancel packges "
4131 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004132 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004133 throw new SecurityException(msg);
4134 }
4135 } catch (RemoteException e) {
4136 throw new SecurityException(e);
4137 }
4138 cancelIntentSenderLocked(rec, true);
4139 }
4140 }
4141
4142 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
4143 rec.canceled = true;
4144 mIntentSenderRecords.remove(rec.key);
4145 if (cleanActivity && rec.key.activity != null) {
4146 rec.key.activity.pendingResults.remove(rec.ref);
4147 }
4148 }
4149
4150 public String getPackageForIntentSender(IIntentSender pendingResult) {
4151 if (!(pendingResult instanceof PendingIntentRecord)) {
4152 return null;
4153 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07004154 try {
4155 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
4156 return res.key.packageName;
4157 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004158 }
4159 return null;
4160 }
4161
Dianne Hackborn6c418d52011-06-29 14:05:33 -07004162 public boolean isIntentSenderTargetedToPackage(IIntentSender pendingResult) {
4163 if (!(pendingResult instanceof PendingIntentRecord)) {
4164 return false;
4165 }
4166 try {
4167 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
4168 if (res.key.allIntents == null) {
4169 return false;
4170 }
4171 for (int i=0; i<res.key.allIntents.length; i++) {
4172 Intent intent = res.key.allIntents[i];
4173 if (intent.getPackage() != null && intent.getComponent() != null) {
4174 return false;
4175 }
4176 }
4177 return true;
4178 } catch (ClassCastException e) {
4179 }
4180 return false;
4181 }
4182
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004183 public void setProcessLimit(int max) {
4184 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4185 "setProcessLimit()");
4186 mProcessLimit = max;
4187 }
4188
4189 public int getProcessLimit() {
4190 return mProcessLimit;
4191 }
4192
4193 void foregroundTokenDied(ForegroundToken token) {
4194 synchronized (ActivityManagerService.this) {
4195 synchronized (mPidsSelfLocked) {
4196 ForegroundToken cur
4197 = mForegroundProcesses.get(token.pid);
4198 if (cur != token) {
4199 return;
4200 }
4201 mForegroundProcesses.remove(token.pid);
4202 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
4203 if (pr == null) {
4204 return;
4205 }
4206 pr.forcingToForeground = null;
4207 pr.foregroundServices = false;
4208 }
4209 updateOomAdjLocked();
4210 }
4211 }
4212
4213 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
4214 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4215 "setProcessForeground()");
4216 synchronized(this) {
4217 boolean changed = false;
4218
4219 synchronized (mPidsSelfLocked) {
4220 ProcessRecord pr = mPidsSelfLocked.get(pid);
4221 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004222 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004223 return;
4224 }
4225 ForegroundToken oldToken = mForegroundProcesses.get(pid);
4226 if (oldToken != null) {
4227 oldToken.token.unlinkToDeath(oldToken, 0);
4228 mForegroundProcesses.remove(pid);
4229 pr.forcingToForeground = null;
4230 changed = true;
4231 }
4232 if (isForeground && token != null) {
4233 ForegroundToken newToken = new ForegroundToken() {
4234 public void binderDied() {
4235 foregroundTokenDied(this);
4236 }
4237 };
4238 newToken.pid = pid;
4239 newToken.token = token;
4240 try {
4241 token.linkToDeath(newToken, 0);
4242 mForegroundProcesses.put(pid, newToken);
4243 pr.forcingToForeground = token;
4244 changed = true;
4245 } catch (RemoteException e) {
4246 // If the process died while doing this, we will later
4247 // do the cleanup with the process death link.
4248 }
4249 }
4250 }
4251
4252 if (changed) {
4253 updateOomAdjLocked();
4254 }
4255 }
4256 }
4257
4258 // =========================================================
4259 // PERMISSIONS
4260 // =========================================================
4261
4262 static class PermissionController extends IPermissionController.Stub {
4263 ActivityManagerService mActivityManagerService;
4264 PermissionController(ActivityManagerService activityManagerService) {
4265 mActivityManagerService = activityManagerService;
4266 }
4267
4268 public boolean checkPermission(String permission, int pid, int uid) {
4269 return mActivityManagerService.checkPermission(permission, pid,
4270 uid) == PackageManager.PERMISSION_GRANTED;
4271 }
4272 }
4273
4274 /**
4275 * This can be called with or without the global lock held.
4276 */
4277 int checkComponentPermission(String permission, int pid, int uid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004278 int owningUid, boolean exported) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004279 // We might be performing an operation on behalf of an indirect binder
4280 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
4281 // client identity accordingly before proceeding.
4282 Identity tlsIdentity = sCallerIdentity.get();
4283 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004284 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004285 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
4286 uid = tlsIdentity.uid;
4287 pid = tlsIdentity.pid;
4288 }
4289
4290 // Root, system server and our own process get to do everything.
Jeff Brown10e89712011-07-08 18:52:57 -07004291 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004292 return PackageManager.PERMISSION_GRANTED;
4293 }
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004294 // If there is a uid that owns whatever is being accessed, it has
4295 // blanket access to it regardless of the permissions it requires.
4296 if (owningUid >= 0 && uid == owningUid) {
4297 return PackageManager.PERMISSION_GRANTED;
4298 }
4299 // If the target is not exported, then nobody else can get to it.
4300 if (!exported) {
4301 Slog.w(TAG, "Permission denied: checkComponentPermission() owningUid=" + owningUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004302 return PackageManager.PERMISSION_DENIED;
4303 }
4304 if (permission == null) {
4305 return PackageManager.PERMISSION_GRANTED;
4306 }
4307 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004308 return AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004309 .checkUidPermission(permission, uid);
4310 } catch (RemoteException e) {
4311 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004312 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004313 }
4314 return PackageManager.PERMISSION_DENIED;
4315 }
4316
4317 /**
4318 * As the only public entry point for permissions checking, this method
4319 * can enforce the semantic that requesting a check on a null global
4320 * permission is automatically denied. (Internally a null permission
4321 * string is used when calling {@link #checkComponentPermission} in cases
4322 * when only uid-based security is needed.)
4323 *
4324 * This can be called with or without the global lock held.
4325 */
4326 public int checkPermission(String permission, int pid, int uid) {
4327 if (permission == null) {
4328 return PackageManager.PERMISSION_DENIED;
4329 }
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004330 return checkComponentPermission(permission, pid, uid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004331 }
4332
4333 /**
4334 * Binder IPC calls go through the public entry point.
4335 * This can be called with or without the global lock held.
4336 */
4337 int checkCallingPermission(String permission) {
4338 return checkPermission(permission,
4339 Binder.getCallingPid(),
4340 Binder.getCallingUid());
4341 }
4342
4343 /**
4344 * This can be called with or without the global lock held.
4345 */
4346 void enforceCallingPermission(String permission, String func) {
4347 if (checkCallingPermission(permission)
4348 == PackageManager.PERMISSION_GRANTED) {
4349 return;
4350 }
4351
4352 String msg = "Permission Denial: " + func + " from pid="
4353 + Binder.getCallingPid()
4354 + ", uid=" + Binder.getCallingUid()
4355 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004356 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004357 throw new SecurityException(msg);
4358 }
4359
4360 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
Dianne Hackborn48058e82010-09-27 16:53:23 -07004361 ProviderInfo pi, Uri uri, int uid, int modeFlags) {
4362 boolean readPerm = (modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0;
4363 boolean writePerm = (modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0;
4364 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4365 "checkHoldingPermissionsLocked: uri=" + uri + " uid=" + uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004366 try {
Dianne Hackborn48058e82010-09-27 16:53:23 -07004367 // Is the component private from the target uid?
4368 final boolean prv = !pi.exported && pi.applicationInfo.uid != uid;
4369
4370 // Acceptable if the there is no read permission needed from the
4371 // target or the target is holding the read permission.
4372 if (!readPerm) {
4373 if ((!prv && pi.readPermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004374 (pm.checkUidPermission(pi.readPermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004375 == PackageManager.PERMISSION_GRANTED)) {
4376 readPerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004377 }
4378 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004379
4380 // Acceptable if the there is no write permission needed from the
4381 // target or the target is holding the read permission.
4382 if (!writePerm) {
4383 if (!prv && (pi.writePermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004384 (pm.checkUidPermission(pi.writePermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004385 == PackageManager.PERMISSION_GRANTED)) {
4386 writePerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004387 }
4388 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004389
4390 // Acceptable if there is a path permission matching the URI that
4391 // the target holds the permission on.
4392 PathPermission[] pps = pi.pathPermissions;
4393 if (pps != null && (!readPerm || !writePerm)) {
4394 final String path = uri.getPath();
4395 int i = pps.length;
4396 while (i > 0 && (!readPerm || !writePerm)) {
4397 i--;
4398 PathPermission pp = pps[i];
4399 if (!readPerm) {
4400 final String pprperm = pp.getReadPermission();
4401 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking read perm for "
4402 + pprperm + " for " + pp.getPath()
4403 + ": match=" + pp.match(path)
4404 + " check=" + pm.checkUidPermission(pprperm, uid));
4405 if (pprperm != null && pp.match(path) &&
4406 (pm.checkUidPermission(pprperm, uid)
4407 == PackageManager.PERMISSION_GRANTED)) {
4408 readPerm = true;
4409 }
4410 }
4411 if (!writePerm) {
4412 final String ppwperm = pp.getWritePermission();
4413 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking write perm "
4414 + ppwperm + " for " + pp.getPath()
4415 + ": match=" + pp.match(path)
4416 + " check=" + pm.checkUidPermission(ppwperm, uid));
4417 if (ppwperm != null && pp.match(path) &&
4418 (pm.checkUidPermission(ppwperm, uid)
4419 == PackageManager.PERMISSION_GRANTED)) {
4420 writePerm = true;
4421 }
4422 }
4423 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004424 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004425 } catch (RemoteException e) {
4426 return false;
4427 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004428
4429 return readPerm && writePerm;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004430 }
4431
4432 private final boolean checkUriPermissionLocked(Uri uri, int uid,
4433 int modeFlags) {
4434 // Root gets to do everything.
Jeff Brown10e89712011-07-08 18:52:57 -07004435 if (uid == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004436 return true;
4437 }
4438 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
4439 if (perms == null) return false;
4440 UriPermission perm = perms.get(uri);
4441 if (perm == null) return false;
4442 return (modeFlags&perm.modeFlags) == modeFlags;
4443 }
4444
4445 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
4446 // Another redirected-binder-call permissions check as in
4447 // {@link checkComponentPermission}.
4448 Identity tlsIdentity = sCallerIdentity.get();
4449 if (tlsIdentity != null) {
4450 uid = tlsIdentity.uid;
4451 pid = tlsIdentity.pid;
4452 }
4453
4454 // Our own process gets to do everything.
4455 if (pid == MY_PID) {
4456 return PackageManager.PERMISSION_GRANTED;
4457 }
4458 synchronized(this) {
4459 return checkUriPermissionLocked(uri, uid, modeFlags)
4460 ? PackageManager.PERMISSION_GRANTED
4461 : PackageManager.PERMISSION_DENIED;
4462 }
4463 }
4464
Dianne Hackborn39792d22010-08-19 18:01:52 -07004465 /**
4466 * Check if the targetPkg can be granted permission to access uri by
4467 * the callingUid using the given modeFlags. Throws a security exception
4468 * if callingUid is not allowed to do this. Returns the uid of the target
4469 * if the URI permission grant should be performed; returns -1 if it is not
4470 * needed (for example targetPkg already has permission to access the URI).
4471 */
4472 int checkGrantUriPermissionLocked(int callingUid, String targetPkg,
4473 Uri uri, int modeFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004474 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4475 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4476 if (modeFlags == 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004477 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004478 }
4479
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004480 if (targetPkg != null) {
4481 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4482 "Checking grant " + targetPkg + " permission to " + uri);
4483 }
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004484
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004485 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004486
4487 // If this is not a content: uri, we can't do anything with it.
4488 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004489 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004490 "Can't grant URI permission for non-content URI: " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004491 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004492 }
4493
4494 String name = uri.getAuthority();
4495 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004496 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004497 if (cpr != null) {
4498 pi = cpr.info;
4499 } else {
4500 try {
4501 pi = pm.resolveContentProvider(name,
4502 PackageManager.GET_URI_PERMISSION_PATTERNS);
4503 } catch (RemoteException ex) {
4504 }
4505 }
4506 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004507 Slog.w(TAG, "No content provider found for: " + name);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004508 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004509 }
4510
4511 int targetUid;
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004512 if (targetPkg != null) {
4513 try {
4514 targetUid = pm.getPackageUid(targetPkg);
4515 if (targetUid < 0) {
4516 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4517 "Can't grant URI permission no uid for: " + targetPkg);
4518 return -1;
4519 }
4520 } catch (RemoteException ex) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004521 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004522 }
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004523 } else {
4524 targetUid = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004525 }
4526
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004527 if (targetUid >= 0) {
4528 // First... does the target actually need this permission?
4529 if (checkHoldingPermissionsLocked(pm, pi, uri, targetUid, modeFlags)) {
4530 // No need to grant the target this permission.
4531 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4532 "Target " + targetPkg + " already has full permission to " + uri);
4533 return -1;
4534 }
4535 } else {
4536 // First... there is no target package, so can anyone access it?
4537 boolean allowed = pi.exported;
4538 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4539 if (pi.readPermission != null) {
4540 allowed = false;
4541 }
4542 }
4543 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4544 if (pi.writePermission != null) {
4545 allowed = false;
4546 }
4547 }
4548 if (allowed) {
4549 return -1;
4550 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004551 }
4552
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004553 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004554 if (!pi.grantUriPermissions) {
4555 throw new SecurityException("Provider " + pi.packageName
4556 + "/" + pi.name
4557 + " does not allow granting of Uri permissions (uri "
4558 + uri + ")");
4559 }
4560 if (pi.uriPermissionPatterns != null) {
4561 final int N = pi.uriPermissionPatterns.length;
4562 boolean allowed = false;
4563 for (int i=0; i<N; i++) {
4564 if (pi.uriPermissionPatterns[i] != null
4565 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
4566 allowed = true;
4567 break;
4568 }
4569 }
4570 if (!allowed) {
4571 throw new SecurityException("Provider " + pi.packageName
4572 + "/" + pi.name
4573 + " does not allow granting of permission to path of Uri "
4574 + uri);
4575 }
4576 }
4577
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004578 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004579 // this uri?
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004580 if (callingUid != Process.myUid()) {
4581 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
4582 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4583 throw new SecurityException("Uid " + callingUid
4584 + " does not have permission to uri " + uri);
4585 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004586 }
4587 }
4588
Dianne Hackborn39792d22010-08-19 18:01:52 -07004589 return targetUid;
4590 }
4591
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004592 public int checkGrantUriPermission(int callingUid, String targetPkg,
4593 Uri uri, int modeFlags) {
4594 synchronized(this) {
4595 return checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4596 }
4597 }
4598
Dianne Hackborn39792d22010-08-19 18:01:52 -07004599 void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg,
4600 Uri uri, int modeFlags, UriPermissionOwner owner) {
4601 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4602 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4603 if (modeFlags == 0) {
4604 return;
4605 }
4606
4607 // So here we are: the caller has the assumed permission
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004608 // to the uri, and the target doesn't. Let's now give this to
4609 // the target.
4610
Joe Onorato8a9b2202010-02-26 18:56:32 -08004611 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004612 "Granting " + targetPkg + "/" + targetUid + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004613
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004614 HashMap<Uri, UriPermission> targetUris
4615 = mGrantedUriPermissions.get(targetUid);
4616 if (targetUris == null) {
4617 targetUris = new HashMap<Uri, UriPermission>();
4618 mGrantedUriPermissions.put(targetUid, targetUris);
4619 }
4620
4621 UriPermission perm = targetUris.get(uri);
4622 if (perm == null) {
4623 perm = new UriPermission(targetUid, uri);
4624 targetUris.put(uri, perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004625 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004626
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004627 perm.modeFlags |= modeFlags;
Dianne Hackborn39792d22010-08-19 18:01:52 -07004628 if (owner == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004629 perm.globalModeFlags |= modeFlags;
Vairavan Srinivasan91c12c22011-01-21 18:26:06 -08004630 } else {
4631 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4632 perm.readOwners.add(owner);
4633 owner.addReadPermission(perm);
4634 }
4635 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4636 perm.writeOwners.add(owner);
4637 owner.addWritePermission(perm);
4638 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004639 }
4640 }
4641
Dianne Hackborn39792d22010-08-19 18:01:52 -07004642 void grantUriPermissionLocked(int callingUid,
4643 String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) {
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004644 if (targetPkg == null) {
4645 throw new NullPointerException("targetPkg");
4646 }
4647
Dianne Hackborn39792d22010-08-19 18:01:52 -07004648 int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4649 if (targetUid < 0) {
4650 return;
4651 }
4652
4653 grantUriPermissionUncheckedLocked(targetUid, targetPkg, uri, modeFlags, owner);
4654 }
4655
4656 /**
4657 * Like checkGrantUriPermissionLocked, but takes an Intent.
4658 */
4659 int checkGrantUriPermissionFromIntentLocked(int callingUid,
4660 String targetPkg, Intent intent) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07004661 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004662 "Checking URI perm to " + (intent != null ? intent.getData() : null)
Dianne Hackbornb424b632010-08-18 15:59:05 -07004663 + " from " + intent + "; flags=0x"
4664 + Integer.toHexString(intent != null ? intent.getFlags() : 0));
4665
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004666 if (targetPkg == null) {
4667 throw new NullPointerException("targetPkg");
4668 }
4669
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004670 if (intent == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004671 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004672 }
4673 Uri data = intent.getData();
4674 if (data == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004675 return -1;
4676 }
4677 return checkGrantUriPermissionLocked(callingUid, targetPkg, data,
4678 intent.getFlags());
4679 }
4680
4681 /**
4682 * Like grantUriPermissionUncheckedLocked, but takes an Intent.
4683 */
4684 void grantUriPermissionUncheckedFromIntentLocked(int targetUid,
4685 String targetPkg, Intent intent, UriPermissionOwner owner) {
4686 grantUriPermissionUncheckedLocked(targetUid, targetPkg, intent.getData(),
4687 intent.getFlags(), owner);
4688 }
4689
4690 void grantUriPermissionFromIntentLocked(int callingUid,
4691 String targetPkg, Intent intent, UriPermissionOwner owner) {
4692 int targetUid = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg, intent);
4693 if (targetUid < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004694 return;
4695 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07004696
4697 grantUriPermissionUncheckedFromIntentLocked(targetUid, targetPkg, intent, owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004698 }
4699
4700 public void grantUriPermission(IApplicationThread caller, String targetPkg,
4701 Uri uri, int modeFlags) {
4702 synchronized(this) {
4703 final ProcessRecord r = getRecordForAppLocked(caller);
4704 if (r == null) {
4705 throw new SecurityException("Unable to find app for caller "
4706 + caller
4707 + " when granting permission to uri " + uri);
4708 }
4709 if (targetPkg == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004710 throw new IllegalArgumentException("null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004711 }
4712 if (uri == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004713 throw new IllegalArgumentException("null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004714 }
4715
4716 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
4717 null);
4718 }
4719 }
4720
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004721 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004722 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
4723 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
4724 HashMap<Uri, UriPermission> perms
4725 = mGrantedUriPermissions.get(perm.uid);
4726 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004727 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004728 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004729 perms.remove(perm.uri);
4730 if (perms.size() == 0) {
4731 mGrantedUriPermissions.remove(perm.uid);
4732 }
4733 }
4734 }
4735 }
4736
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004737 private void revokeUriPermissionLocked(int callingUid, Uri uri,
4738 int modeFlags) {
4739 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4740 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4741 if (modeFlags == 0) {
4742 return;
4743 }
4744
Joe Onorato8a9b2202010-02-26 18:56:32 -08004745 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004746 "Revoking all granted permissions to " + uri);
4747
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004748 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004749
4750 final String authority = uri.getAuthority();
4751 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004752 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004753 if (cpr != null) {
4754 pi = cpr.info;
4755 } else {
4756 try {
4757 pi = pm.resolveContentProvider(authority,
4758 PackageManager.GET_URI_PERMISSION_PATTERNS);
4759 } catch (RemoteException ex) {
4760 }
4761 }
4762 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004763 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004764 return;
4765 }
4766
4767 // Does the caller have this permission on the URI?
Dianne Hackborn48058e82010-09-27 16:53:23 -07004768 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004769 // Right now, if you are not the original owner of the permission,
4770 // you are not allowed to revoke it.
4771 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4772 throw new SecurityException("Uid " + callingUid
4773 + " does not have permission to uri " + uri);
4774 //}
4775 }
4776
4777 // Go through all of the permissions and remove any that match.
4778 final List<String> SEGMENTS = uri.getPathSegments();
4779 if (SEGMENTS != null) {
4780 final int NS = SEGMENTS.size();
4781 int N = mGrantedUriPermissions.size();
4782 for (int i=0; i<N; i++) {
4783 HashMap<Uri, UriPermission> perms
4784 = mGrantedUriPermissions.valueAt(i);
4785 Iterator<UriPermission> it = perms.values().iterator();
4786 toploop:
4787 while (it.hasNext()) {
4788 UriPermission perm = it.next();
4789 Uri targetUri = perm.uri;
4790 if (!authority.equals(targetUri.getAuthority())) {
4791 continue;
4792 }
4793 List<String> targetSegments = targetUri.getPathSegments();
4794 if (targetSegments == null) {
4795 continue;
4796 }
4797 if (targetSegments.size() < NS) {
4798 continue;
4799 }
4800 for (int j=0; j<NS; j++) {
4801 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
4802 continue toploop;
4803 }
4804 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004805 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004806 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004807 perm.clearModes(modeFlags);
4808 if (perm.modeFlags == 0) {
4809 it.remove();
4810 }
4811 }
4812 if (perms.size() == 0) {
4813 mGrantedUriPermissions.remove(
4814 mGrantedUriPermissions.keyAt(i));
4815 N--;
4816 i--;
4817 }
4818 }
4819 }
4820 }
4821
4822 public void revokeUriPermission(IApplicationThread caller, Uri uri,
4823 int modeFlags) {
4824 synchronized(this) {
4825 final ProcessRecord r = getRecordForAppLocked(caller);
4826 if (r == null) {
4827 throw new SecurityException("Unable to find app for caller "
4828 + caller
4829 + " when revoking permission to uri " + uri);
4830 }
4831 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004832 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004833 return;
4834 }
4835
4836 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4837 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4838 if (modeFlags == 0) {
4839 return;
4840 }
4841
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004842 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004843
4844 final String authority = uri.getAuthority();
4845 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004846 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004847 if (cpr != null) {
4848 pi = cpr.info;
4849 } else {
4850 try {
4851 pi = pm.resolveContentProvider(authority,
4852 PackageManager.GET_URI_PERMISSION_PATTERNS);
4853 } catch (RemoteException ex) {
4854 }
4855 }
4856 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004857 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004858 return;
4859 }
4860
4861 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
4862 }
4863 }
4864
Dianne Hackborn7e269642010-08-25 19:50:20 -07004865 @Override
4866 public IBinder newUriPermissionOwner(String name) {
4867 synchronized(this) {
4868 UriPermissionOwner owner = new UriPermissionOwner(this, name);
4869 return owner.getExternalTokenLocked();
4870 }
4871 }
4872
4873 @Override
4874 public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg,
4875 Uri uri, int modeFlags) {
4876 synchronized(this) {
4877 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4878 if (owner == null) {
4879 throw new IllegalArgumentException("Unknown owner: " + token);
4880 }
4881 if (fromUid != Binder.getCallingUid()) {
4882 if (Binder.getCallingUid() != Process.myUid()) {
4883 // Only system code can grant URI permissions on behalf
4884 // of other users.
4885 throw new SecurityException("nice try");
4886 }
4887 }
4888 if (targetPkg == null) {
4889 throw new IllegalArgumentException("null target");
4890 }
4891 if (uri == null) {
4892 throw new IllegalArgumentException("null uri");
4893 }
4894
4895 grantUriPermissionLocked(fromUid, targetPkg, uri, modeFlags, owner);
4896 }
4897 }
4898
4899 @Override
4900 public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode) {
4901 synchronized(this) {
4902 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4903 if (owner == null) {
4904 throw new IllegalArgumentException("Unknown owner: " + token);
4905 }
4906
4907 if (uri == null) {
4908 owner.removeUriPermissionsLocked(mode);
4909 } else {
4910 owner.removeUriPermissionLocked(uri, mode);
4911 }
4912 }
4913 }
4914
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004915 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
4916 synchronized (this) {
4917 ProcessRecord app =
4918 who != null ? getRecordForAppLocked(who) : null;
4919 if (app == null) return;
4920
4921 Message msg = Message.obtain();
4922 msg.what = WAIT_FOR_DEBUGGER_MSG;
4923 msg.obj = app;
4924 msg.arg1 = waiting ? 1 : 0;
4925 mHandler.sendMessage(msg);
4926 }
4927 }
4928
4929 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
4930 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08004931 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004932 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08004933 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004934 }
4935
4936 // =========================================================
4937 // TASK MANAGEMENT
4938 // =========================================================
4939
4940 public List getTasks(int maxNum, int flags,
4941 IThumbnailReceiver receiver) {
4942 ArrayList list = new ArrayList();
4943
4944 PendingThumbnailsRecord pending = null;
4945 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004946 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004947
4948 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004949 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004950 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
4951 + ", receiver=" + receiver);
4952
4953 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
4954 != PackageManager.PERMISSION_GRANTED) {
4955 if (receiver != null) {
4956 // If the caller wants to wait for pending thumbnails,
4957 // it ain't gonna get them.
4958 try {
4959 receiver.finished();
4960 } catch (RemoteException ex) {
4961 }
4962 }
4963 String msg = "Permission Denial: getTasks() from pid="
4964 + Binder.getCallingPid()
4965 + ", uid=" + Binder.getCallingUid()
4966 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004967 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004968 throw new SecurityException(msg);
4969 }
4970
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004971 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004972 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004973 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004974 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004975 TaskRecord curTask = null;
4976 int numActivities = 0;
4977 int numRunning = 0;
4978 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004979 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004980 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004981 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004982
4983 // Initialize state for next task if needed.
4984 if (top == null ||
4985 (top.state == ActivityState.INITIALIZING
4986 && top.task == r.task)) {
4987 top = r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004988 curTask = r.task;
4989 numActivities = numRunning = 0;
4990 }
4991
4992 // Add 'r' into the current task.
4993 numActivities++;
4994 if (r.app != null && r.app.thread != null) {
4995 numRunning++;
4996 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004997
Joe Onorato8a9b2202010-02-26 18:56:32 -08004998 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004999 TAG, r.intent.getComponent().flattenToShortString()
5000 + ": task=" + r.task);
5001
5002 // If the next one is a different task, generate a new
5003 // TaskInfo entry for what we have.
5004 if (next == null || next.task != curTask) {
5005 ActivityManager.RunningTaskInfo ci
5006 = new ActivityManager.RunningTaskInfo();
5007 ci.id = curTask.taskId;
5008 ci.baseActivity = r.intent.getComponent();
5009 ci.topActivity = top.intent.getComponent();
Dianne Hackbornf26fd992011-04-08 18:14:09 -07005010 if (top.thumbHolder != null) {
5011 ci.description = top.thumbHolder.lastDescription;
5012 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005013 ci.numActivities = numActivities;
5014 ci.numRunning = numRunning;
5015 //System.out.println(
5016 // "#" + maxNum + ": " + " descr=" + ci.description);
5017 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005018 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005019 TAG, "State=" + top.state + "Idle=" + top.idle
5020 + " app=" + top.app
5021 + " thr=" + (top.app != null ? top.app.thread : null));
5022 if (top.state == ActivityState.RESUMED
5023 || top.state == ActivityState.PAUSING) {
5024 if (top.idle && top.app != null
5025 && top.app.thread != null) {
5026 topRecord = top;
5027 topThumbnail = top.app.thread;
5028 } else {
5029 top.thumbnailNeeded = true;
5030 }
5031 }
5032 if (pending == null) {
5033 pending = new PendingThumbnailsRecord(receiver);
5034 }
5035 pending.pendingRecords.add(top);
5036 }
5037 list.add(ci);
5038 maxNum--;
5039 top = null;
5040 }
5041 }
5042
5043 if (pending != null) {
5044 mPendingThumbnails.add(pending);
5045 }
5046 }
5047
Joe Onorato8a9b2202010-02-26 18:56:32 -08005048 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005049
5050 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005051 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005052 try {
5053 topThumbnail.requestThumbnail(topRecord);
5054 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005055 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005056 sendPendingThumbnail(null, topRecord, null, null, true);
5057 }
5058 }
5059
5060 if (pending == null && receiver != null) {
5061 // In this case all thumbnails were available and the client
5062 // is being asked to be told when the remaining ones come in...
5063 // which is unusually, since the top-most currently running
5064 // activity should never have a canned thumbnail! Oh well.
5065 try {
5066 receiver.finished();
5067 } catch (RemoteException ex) {
5068 }
5069 }
5070
5071 return list;
5072 }
5073
5074 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
5075 int flags) {
5076 synchronized (this) {
5077 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
5078 "getRecentTasks()");
5079
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005080 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07005081
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005082 final int N = mRecentTasks.size();
5083 ArrayList<ActivityManager.RecentTaskInfo> res
5084 = new ArrayList<ActivityManager.RecentTaskInfo>(
5085 maxNum < N ? maxNum : N);
5086 for (int i=0; i<N && maxNum > 0; i++) {
5087 TaskRecord tr = mRecentTasks.get(i);
5088 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
5089 || (tr.intent == null)
5090 || ((tr.intent.getFlags()
5091 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
5092 ActivityManager.RecentTaskInfo rti
5093 = new ActivityManager.RecentTaskInfo();
5094 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
Dianne Hackbornd94df452011-02-16 18:53:31 -08005095 rti.persistentId = tr.taskId;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005096 rti.baseIntent = new Intent(
5097 tr.intent != null ? tr.intent : tr.affinityIntent);
5098 rti.origActivity = tr.origActivity;
Dianne Hackbornd2835932010-12-13 16:28:46 -08005099 rti.description = tr.lastDescription;
5100
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07005101 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
5102 // Check whether this activity is currently available.
5103 try {
5104 if (rti.origActivity != null) {
5105 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
5106 continue;
5107 }
5108 } else if (rti.baseIntent != null) {
5109 if (pm.queryIntentActivities(rti.baseIntent,
5110 null, 0) == null) {
5111 continue;
5112 }
5113 }
5114 } catch (RemoteException e) {
5115 // Will never happen.
5116 }
5117 }
5118
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005119 res.add(rti);
5120 maxNum--;
5121 }
5122 }
5123 return res;
5124 }
5125 }
5126
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005127 private TaskRecord taskForIdLocked(int id) {
5128 final int N = mRecentTasks.size();
5129 for (int i=0; i<N; i++) {
5130 TaskRecord tr = mRecentTasks.get(i);
5131 if (tr.taskId == id) {
5132 return tr;
Dianne Hackbornd94df452011-02-16 18:53:31 -08005133 }
5134 }
5135 return null;
5136 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005137
5138 public ActivityManager.TaskThumbnails getTaskThumbnails(int id) {
5139 synchronized (this) {
5140 enforceCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER,
5141 "getTaskThumbnails()");
5142 TaskRecord tr = taskForIdLocked(id);
5143 if (tr != null) {
5144 return mMainStack.getTaskThumbnailsLocked(tr);
5145 }
5146 }
5147 return null;
5148 }
5149
5150 public boolean removeSubTask(int taskId, int subTaskIndex) {
5151 synchronized (this) {
5152 enforceCallingPermission(android.Manifest.permission.REMOVE_TASKS,
5153 "removeSubTask()");
5154 long ident = Binder.clearCallingIdentity();
5155 try {
5156 return mMainStack.removeTaskActivitiesLocked(taskId, subTaskIndex) != null;
5157 } finally {
5158 Binder.restoreCallingIdentity(ident);
5159 }
5160 }
5161 }
5162
Dianne Hackborn8894cc52011-07-01 16:28:17 -07005163 private void cleanUpRemovedTaskLocked(ActivityRecord root, boolean killProcesses) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005164 TaskRecord tr = root.task;
5165 Intent baseIntent = new Intent(
5166 tr.intent != null ? tr.intent : tr.affinityIntent);
5167 ComponentName component = baseIntent.getComponent();
5168 if (component == null) {
5169 Slog.w(TAG, "Now component for base intent of task: " + tr);
5170 return;
5171 }
5172
5173 // Find any running services associated with this app.
5174 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
5175 for (ServiceRecord sr : mServices.values()) {
5176 if (sr.packageName.equals(component.getPackageName())) {
5177 services.add(sr);
5178 }
5179 }
5180
5181 // Take care of any running services associated with the app.
5182 for (int i=0; i<services.size(); i++) {
5183 ServiceRecord sr = services.get(i);
5184 if (sr.startRequested) {
5185 if ((sr.serviceInfo.flags&ServiceInfo.FLAG_STOP_WITH_TASK) != 0) {
Dianne Hackborn8894cc52011-07-01 16:28:17 -07005186 Slog.i(TAG, "Stopping service " + sr.shortName + ": remove task");
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005187 stopServiceLocked(sr);
5188 } else {
5189 sr.pendingStarts.add(new ServiceRecord.StartItem(sr, true,
5190 sr.makeNextStartId(), baseIntent, -1));
5191 if (sr.app != null && sr.app.thread != null) {
5192 sendServiceArgsLocked(sr, false);
5193 }
5194 }
5195 }
5196 }
5197
Dianne Hackborn8894cc52011-07-01 16:28:17 -07005198 if (killProcesses) {
5199 // Find any running processes associated with this app.
5200 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
5201 SparseArray<ProcessRecord> appProcs
5202 = mProcessNames.getMap().get(component.getPackageName());
5203 if (appProcs != null) {
5204 for (int i=0; i<appProcs.size(); i++) {
5205 procs.add(appProcs.valueAt(i));
5206 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005207 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005208
Dianne Hackborn8894cc52011-07-01 16:28:17 -07005209 // Kill the running processes.
5210 for (int i=0; i<procs.size(); i++) {
5211 ProcessRecord pr = procs.get(i);
5212 if (pr.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {
5213 Slog.i(TAG, "Killing " + pr.toShortString() + ": remove task");
5214 EventLog.writeEvent(EventLogTags.AM_KILL, pr.pid,
5215 pr.processName, pr.setAdj, "remove task");
5216 Process.killProcessQuiet(pr.pid);
5217 } else {
5218 pr.waitingToKill = "remove task";
5219 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005220 }
5221 }
5222 }
5223
5224 public boolean removeTask(int taskId, int flags) {
5225 synchronized (this) {
5226 enforceCallingPermission(android.Manifest.permission.REMOVE_TASKS,
5227 "removeTask()");
5228 long ident = Binder.clearCallingIdentity();
5229 try {
5230 ActivityRecord r = mMainStack.removeTaskActivitiesLocked(taskId, -1);
5231 if (r != null) {
5232 mRecentTasks.remove(r.task);
Dianne Hackborn8894cc52011-07-01 16:28:17 -07005233 cleanUpRemovedTaskLocked(r,
5234 (flags&ActivityManager.REMOVE_TASK_KILL_PROCESS) != 0);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005235 return true;
5236 }
5237 } finally {
5238 Binder.restoreCallingIdentity(ident);
5239 }
5240 }
5241 return false;
5242 }
Dianne Hackbornd94df452011-02-16 18:53:31 -08005243
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005244 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
5245 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005246 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005247 TaskRecord jt = startTask;
5248
5249 // First look backwards
5250 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005251 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005252 if (r.task != jt) {
5253 jt = r.task;
5254 if (affinity.equals(jt.affinity)) {
5255 return j;
5256 }
5257 }
5258 }
5259
5260 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005261 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005262 jt = startTask;
5263 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005264 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005265 if (r.task != jt) {
5266 if (affinity.equals(jt.affinity)) {
5267 return j;
5268 }
5269 jt = r.task;
5270 }
5271 }
5272
5273 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005274 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005275 return N-1;
5276 }
5277
5278 return -1;
5279 }
5280
5281 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005282 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005283 */
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005284 public void moveTaskToFront(int task, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005285 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5286 "moveTaskToFront()");
5287
5288 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005289 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5290 Binder.getCallingUid(), "Task to front")) {
5291 return;
5292 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005293 final long origId = Binder.clearCallingIdentity();
5294 try {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005295 TaskRecord tr = taskForIdLocked(task);
5296 if (tr != null) {
5297 if ((flags&ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
5298 mMainStack.mUserLeaving = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005299 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005300 if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
5301 // Caller wants the home activity moved with it. To accomplish this,
5302 // we'll just move the home task to the top first.
5303 mMainStack.moveHomeToFrontLocked();
5304 }
5305 mMainStack.moveTaskToFrontLocked(tr, null);
5306 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005307 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005308 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
5309 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005310 if (hr.task.taskId == task) {
Dianne Hackbornd94df452011-02-16 18:53:31 -08005311 if ((flags&ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
5312 mMainStack.mUserLeaving = true;
5313 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005314 if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
5315 // Caller wants the home activity moved with it. To accomplish this,
5316 // we'll just move the home task to the top first.
5317 mMainStack.moveHomeToFrontLocked();
5318 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005319 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005320 return;
5321 }
5322 }
5323 } finally {
5324 Binder.restoreCallingIdentity(origId);
5325 }
5326 }
5327 }
5328
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005329 public void moveTaskToBack(int task) {
5330 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5331 "moveTaskToBack()");
5332
5333 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005334 if (mMainStack.mResumedActivity != null
5335 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005336 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5337 Binder.getCallingUid(), "Task to back")) {
5338 return;
5339 }
5340 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005341 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005342 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005343 Binder.restoreCallingIdentity(origId);
5344 }
5345 }
5346
5347 /**
5348 * Moves an activity, and all of the other activities within the same task, to the bottom
5349 * of the history stack. The activity's order within the task is unchanged.
5350 *
5351 * @param token A reference to the activity we wish to move
5352 * @param nonRoot If false then this only works if the activity is the root
5353 * of a task; if true it will work for any activity in a task.
5354 * @return Returns true if the move completed, false if not.
5355 */
5356 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
5357 synchronized(this) {
5358 final long origId = Binder.clearCallingIdentity();
5359 int taskId = getTaskForActivityLocked(token, !nonRoot);
5360 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005361 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005362 }
5363 Binder.restoreCallingIdentity(origId);
5364 }
5365 return false;
5366 }
5367
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005368 public void moveTaskBackwards(int task) {
5369 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5370 "moveTaskBackwards()");
5371
5372 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005373 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5374 Binder.getCallingUid(), "Task backwards")) {
5375 return;
5376 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005377 final long origId = Binder.clearCallingIdentity();
5378 moveTaskBackwardsLocked(task);
5379 Binder.restoreCallingIdentity(origId);
5380 }
5381 }
5382
5383 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005384 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005385 }
5386
5387 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
5388 synchronized(this) {
5389 return getTaskForActivityLocked(token, onlyRoot);
5390 }
5391 }
5392
5393 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005394 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005395 TaskRecord lastTask = null;
5396 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005397 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005398 if (r == token) {
5399 if (!onlyRoot || lastTask != r.task) {
5400 return r.task.taskId;
5401 }
5402 return -1;
5403 }
5404 lastTask = r.task;
5405 }
5406
5407 return -1;
5408 }
5409
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005410 public void finishOtherInstances(IBinder token, ComponentName className) {
5411 synchronized(this) {
5412 final long origId = Binder.clearCallingIdentity();
5413
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005414 int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005415 TaskRecord lastTask = null;
5416 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005417 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005418 if (r.realActivity.equals(className)
5419 && r != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005420 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005421 null, "others")) {
5422 i--;
5423 N--;
5424 }
5425 }
5426 lastTask = r.task;
5427 }
5428
5429 Binder.restoreCallingIdentity(origId);
5430 }
5431 }
5432
5433 // =========================================================
5434 // THUMBNAILS
5435 // =========================================================
5436
5437 public void reportThumbnail(IBinder token,
5438 Bitmap thumbnail, CharSequence description) {
5439 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
5440 final long origId = Binder.clearCallingIdentity();
5441 sendPendingThumbnail(null, token, thumbnail, description, true);
5442 Binder.restoreCallingIdentity(origId);
5443 }
5444
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005445 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005446 Bitmap thumbnail, CharSequence description, boolean always) {
5447 TaskRecord task = null;
5448 ArrayList receivers = null;
5449
5450 //System.out.println("Send pending thumbnail: " + r);
5451
5452 synchronized(this) {
5453 if (r == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005454 int index = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005455 if (index < 0) {
5456 return;
5457 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005458 r = (ActivityRecord)mMainStack.mHistory.get(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005459 }
Dianne Hackbornf26fd992011-04-08 18:14:09 -07005460 if (thumbnail == null && r.thumbHolder != null) {
5461 thumbnail = r.thumbHolder.lastThumbnail;
5462 description = r.thumbHolder.lastDescription;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005463 }
5464 if (thumbnail == null && !always) {
5465 // If there is no thumbnail, and this entry is not actually
5466 // going away, then abort for now and pick up the next
5467 // thumbnail we get.
5468 return;
5469 }
5470 task = r.task;
5471
5472 int N = mPendingThumbnails.size();
5473 int i=0;
5474 while (i<N) {
5475 PendingThumbnailsRecord pr =
5476 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
5477 //System.out.println("Looking in " + pr.pendingRecords);
5478 if (pr.pendingRecords.remove(r)) {
5479 if (receivers == null) {
5480 receivers = new ArrayList();
5481 }
5482 receivers.add(pr);
5483 if (pr.pendingRecords.size() == 0) {
5484 pr.finished = true;
5485 mPendingThumbnails.remove(i);
5486 N--;
5487 continue;
5488 }
5489 }
5490 i++;
5491 }
5492 }
5493
5494 if (receivers != null) {
5495 final int N = receivers.size();
5496 for (int i=0; i<N; i++) {
5497 try {
5498 PendingThumbnailsRecord pr =
5499 (PendingThumbnailsRecord)receivers.get(i);
5500 pr.receiver.newThumbnail(
5501 task != null ? task.taskId : -1, thumbnail, description);
5502 if (pr.finished) {
5503 pr.receiver.finished();
5504 }
5505 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005506 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005507 }
5508 }
5509 }
5510 }
5511
5512 // =========================================================
5513 // CONTENT PROVIDERS
5514 // =========================================================
5515
Jeff Brown10e89712011-07-08 18:52:57 -07005516 private final List<ProviderInfo> generateApplicationProvidersLocked(ProcessRecord app) {
5517 List<ProviderInfo> providers = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005518 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005519 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005520 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005521 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005522 } catch (RemoteException ex) {
5523 }
5524 if (providers != null) {
5525 final int N = providers.size();
5526 for (int i=0; i<N; i++) {
5527 ProviderInfo cpi =
5528 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005529 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005530 if (cpr == null) {
5531 cpr = new ContentProviderRecord(cpi, app.info);
5532 mProvidersByClass.put(cpi.name, cpr);
5533 }
5534 app.pubProviders.put(cpi.name, cpr);
5535 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005536 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005537 }
5538 }
5539 return providers;
5540 }
5541
5542 private final String checkContentProviderPermissionLocked(
Dianne Hackbornb424b632010-08-18 15:59:05 -07005543 ProviderInfo cpi, ProcessRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005544 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
5545 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
5546 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005547 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005548 == PackageManager.PERMISSION_GRANTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005549 return null;
5550 }
5551 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005552 cpi.applicationInfo.uid, cpi.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005553 == PackageManager.PERMISSION_GRANTED) {
5554 return null;
5555 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005556
5557 PathPermission[] pps = cpi.pathPermissions;
5558 if (pps != null) {
5559 int i = pps.length;
5560 while (i > 0) {
5561 i--;
5562 PathPermission pp = pps[i];
5563 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005564 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005565 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005566 return null;
5567 }
5568 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005569 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005570 == PackageManager.PERMISSION_GRANTED) {
5571 return null;
5572 }
5573 }
5574 }
5575
Dianne Hackbornb424b632010-08-18 15:59:05 -07005576 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
5577 if (perms != null) {
5578 for (Map.Entry<Uri, UriPermission> uri : perms.entrySet()) {
5579 if (uri.getKey().getAuthority().equals(cpi.authority)) {
5580 return null;
5581 }
5582 }
5583 }
5584
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005585 String msg;
5586 if (!cpi.exported) {
5587 msg = "Permission Denial: opening provider " + cpi.name
5588 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5589 + ", uid=" + callingUid + ") that is not exported from uid "
5590 + cpi.applicationInfo.uid;
5591 } else {
5592 msg = "Permission Denial: opening provider " + cpi.name
5593 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5594 + ", uid=" + callingUid + ") requires "
5595 + cpi.readPermission + " or " + cpi.writePermission;
5596 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005597 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005598 return msg;
5599 }
5600
5601 private final ContentProviderHolder getContentProviderImpl(
5602 IApplicationThread caller, String name) {
5603 ContentProviderRecord cpr;
5604 ProviderInfo cpi = null;
5605
5606 synchronized(this) {
5607 ProcessRecord r = null;
5608 if (caller != null) {
5609 r = getRecordForAppLocked(caller);
5610 if (r == null) {
5611 throw new SecurityException(
5612 "Unable to find app for caller " + caller
5613 + " (pid=" + Binder.getCallingPid()
5614 + ") when getting content provider " + name);
5615 }
5616 }
5617
5618 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07005619 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005620 if (cpr != null) {
5621 cpi = cpr.info;
Dianne Hackbornb424b632010-08-18 15:59:05 -07005622 String msg;
5623 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5624 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005625 }
5626
5627 if (r != null && cpr.canRunHere(r)) {
5628 // This provider has been published or is in the process
5629 // of being published... but it is also allowed to run
5630 // in the caller's process, so don't make a connection
5631 // and just let the caller instantiate its own instance.
5632 if (cpr.provider != null) {
5633 // don't give caller the provider object, it needs
5634 // to make its own.
5635 cpr = new ContentProviderRecord(cpr);
5636 }
5637 return cpr;
5638 }
5639
5640 final long origId = Binder.clearCallingIdentity();
5641
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005642 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005643 // return it right away.
5644 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005645 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005646 "Adding provider requested by "
5647 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005648 + cpr.info.processName);
5649 Integer cnt = r.conProviders.get(cpr);
5650 if (cnt == null) {
5651 r.conProviders.put(cpr, new Integer(1));
5652 } else {
5653 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5654 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005655 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07005656 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
5657 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07005658 // make sure to count it as being accessed and thus
5659 // back up on the LRU list. This is good because
5660 // content providers are often expensive to start.
5661 updateLruProcessLocked(cpr.app, false, true);
5662 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07005663 } else {
5664 cpr.externals++;
5665 }
5666
5667 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005668 updateOomAdjLocked(cpr.app);
5669 }
5670
5671 Binder.restoreCallingIdentity(origId);
5672
5673 } else {
5674 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005675 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005676 resolveContentProvider(name,
5677 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005678 } catch (RemoteException ex) {
5679 }
5680 if (cpi == null) {
5681 return null;
5682 }
5683
Dianne Hackbornb424b632010-08-18 15:59:05 -07005684 String msg;
5685 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5686 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005687 }
5688
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07005689 if (!mProcessesReady && !mDidUpdate && !mWaitingUpdate
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005690 && !cpi.processName.equals("system")) {
5691 // If this content provider does not run in the system
5692 // process, and the system is not yet ready to run other
5693 // processes, then fail fast instead of hanging.
5694 throw new IllegalArgumentException(
5695 "Attempt to launch content provider before system ready");
5696 }
5697
Dianne Hackborn860755f2010-06-03 18:47:52 -07005698 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005699 final boolean firstClass = cpr == null;
5700 if (firstClass) {
5701 try {
5702 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005703 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005704 getApplicationInfo(
5705 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005706 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005707 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005708 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005709 + cpi.name);
5710 return null;
5711 }
5712 cpr = new ContentProviderRecord(cpi, ai);
5713 } catch (RemoteException ex) {
5714 // pm is in same process, this will never happen.
5715 }
5716 }
5717
5718 if (r != null && cpr.canRunHere(r)) {
5719 // If this is a multiprocess provider, then just return its
5720 // info and allow the caller to instantiate it. Only do
5721 // this if the provider is the same user as the caller's
5722 // process, or can run as root (so can be in any process).
5723 return cpr;
5724 }
5725
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005726 if (DEBUG_PROVIDER) {
5727 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08005728 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005729 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005730 }
5731
5732 // This is single process, and our app is now connecting to it.
5733 // See if we are already in the process of launching this
5734 // provider.
5735 final int N = mLaunchingProviders.size();
5736 int i;
5737 for (i=0; i<N; i++) {
5738 if (mLaunchingProviders.get(i) == cpr) {
5739 break;
5740 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005741 }
5742
5743 // If the provider is not already being launched, then get it
5744 // started.
5745 if (i >= N) {
5746 final long origId = Binder.clearCallingIdentity();
Dianne Hackborne7f97212011-02-24 14:40:20 -08005747
5748 try {
5749 // Content provider is now in use, its package can't be stopped.
5750 try {
5751 AppGlobals.getPackageManager().setPackageStoppedState(
5752 cpr.appInfo.packageName, false);
5753 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08005754 } catch (IllegalArgumentException e) {
5755 Slog.w(TAG, "Failed trying to unstop package "
5756 + cpr.appInfo.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08005757 }
5758
5759 ProcessRecord proc = startProcessLocked(cpi.processName,
5760 cpr.appInfo, false, 0, "content provider",
5761 new ComponentName(cpi.applicationInfo.packageName,
5762 cpi.name), false);
5763 if (proc == null) {
5764 Slog.w(TAG, "Unable to launch app "
5765 + cpi.applicationInfo.packageName + "/"
5766 + cpi.applicationInfo.uid + " for provider "
5767 + name + ": process is bad");
5768 return null;
5769 }
5770 cpr.launchingApp = proc;
5771 mLaunchingProviders.add(cpr);
5772 } finally {
5773 Binder.restoreCallingIdentity(origId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005774 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005775 }
5776
5777 // Make sure the provider is published (the same provider class
5778 // may be published under multiple names).
5779 if (firstClass) {
5780 mProvidersByClass.put(cpi.name, cpr);
5781 }
5782 mProvidersByName.put(name, cpr);
5783
5784 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005785 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005786 "Adding provider requested by "
5787 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005788 + cpr.info.processName);
5789 Integer cnt = r.conProviders.get(cpr);
5790 if (cnt == null) {
5791 r.conProviders.put(cpr, new Integer(1));
5792 } else {
5793 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5794 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005795 cpr.clients.add(r);
5796 } else {
5797 cpr.externals++;
5798 }
5799 }
5800 }
5801
5802 // Wait for the provider to be published...
5803 synchronized (cpr) {
5804 while (cpr.provider == null) {
5805 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005806 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005807 + cpi.applicationInfo.packageName + "/"
5808 + cpi.applicationInfo.uid + " for provider "
5809 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005810 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005811 cpi.applicationInfo.packageName,
5812 cpi.applicationInfo.uid, name);
5813 return null;
5814 }
5815 try {
5816 cpr.wait();
5817 } catch (InterruptedException ex) {
5818 }
5819 }
5820 }
5821 return cpr;
5822 }
5823
5824 public final ContentProviderHolder getContentProvider(
5825 IApplicationThread caller, String name) {
5826 if (caller == null) {
5827 String msg = "null IApplicationThread when getting content provider "
5828 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005829 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005830 throw new SecurityException(msg);
5831 }
5832
5833 return getContentProviderImpl(caller, name);
5834 }
5835
5836 private ContentProviderHolder getContentProviderExternal(String name) {
5837 return getContentProviderImpl(null, name);
5838 }
5839
5840 /**
5841 * Drop a content provider from a ProcessRecord's bookkeeping
5842 * @param cpr
5843 */
5844 public void removeContentProvider(IApplicationThread caller, String name) {
5845 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005846 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005847 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005848 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005849 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005850 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005851 return;
5852 }
5853 final ProcessRecord r = getRecordForAppLocked(caller);
5854 if (r == null) {
5855 throw new SecurityException(
5856 "Unable to find app for caller " + caller +
5857 " when removing content provider " + name);
5858 }
5859 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005860 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005861 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005862 + r.info.processName + " from process "
5863 + localCpr.appInfo.processName);
5864 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005865 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08005866 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005867 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005868 return;
5869 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005870 Integer cnt = r.conProviders.get(localCpr);
5871 if (cnt == null || cnt.intValue() <= 1) {
5872 localCpr.clients.remove(r);
5873 r.conProviders.remove(localCpr);
5874 } else {
5875 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
5876 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005877 }
5878 updateOomAdjLocked();
5879 }
5880 }
5881
5882 private void removeContentProviderExternal(String name) {
5883 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005884 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005885 if(cpr == null) {
5886 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005887 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005888 return;
5889 }
5890
5891 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005892 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005893 localCpr.externals--;
5894 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005895 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005896 }
5897 updateOomAdjLocked();
5898 }
5899 }
5900
5901 public final void publishContentProviders(IApplicationThread caller,
5902 List<ContentProviderHolder> providers) {
5903 if (providers == null) {
5904 return;
5905 }
5906
5907 synchronized(this) {
5908 final ProcessRecord r = getRecordForAppLocked(caller);
5909 if (r == null) {
5910 throw new SecurityException(
5911 "Unable to find app for caller " + caller
5912 + " (pid=" + Binder.getCallingPid()
5913 + ") when publishing content providers");
5914 }
5915
5916 final long origId = Binder.clearCallingIdentity();
5917
5918 final int N = providers.size();
5919 for (int i=0; i<N; i++) {
5920 ContentProviderHolder src = providers.get(i);
5921 if (src == null || src.info == null || src.provider == null) {
5922 continue;
5923 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005924 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005925 if (dst != null) {
5926 mProvidersByClass.put(dst.info.name, dst);
5927 String names[] = dst.info.authority.split(";");
5928 for (int j = 0; j < names.length; j++) {
5929 mProvidersByName.put(names[j], dst);
5930 }
5931
5932 int NL = mLaunchingProviders.size();
5933 int j;
5934 for (j=0; j<NL; j++) {
5935 if (mLaunchingProviders.get(j) == dst) {
5936 mLaunchingProviders.remove(j);
5937 j--;
5938 NL--;
5939 }
5940 }
5941 synchronized (dst) {
5942 dst.provider = src.provider;
5943 dst.app = r;
5944 dst.notifyAll();
5945 }
5946 updateOomAdjLocked(r);
5947 }
5948 }
5949
5950 Binder.restoreCallingIdentity(origId);
5951 }
5952 }
5953
5954 public static final void installSystemProviders() {
Jeff Brown10e89712011-07-08 18:52:57 -07005955 List<ProviderInfo> providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06005956 synchronized (mSelf) {
5957 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
5958 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005959 if (providers != null) {
5960 for (int i=providers.size()-1; i>=0; i--) {
5961 ProviderInfo pi = (ProviderInfo)providers.get(i);
5962 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5963 Slog.w(TAG, "Not installing system proc provider " + pi.name
5964 + ": not system .apk");
5965 providers.remove(i);
5966 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005967 }
5968 }
5969 }
Josh Bartel2ecce342010-02-25 10:55:48 -06005970 if (providers != null) {
5971 mSystemThread.installSystemProviders(providers);
5972 }
Svetoslav Ganov54d068e2011-03-02 12:58:40 -08005973
5974 mSelf.mCoreSettingsObserver = new CoreSettingsObserver(mSelf);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005975 }
5976
Dianne Hackborncca1f0e2010-09-26 18:34:53 -07005977 /**
5978 * Allows app to retrieve the MIME type of a URI without having permission
5979 * to access its content provider.
5980 *
5981 * CTS tests for this functionality can be run with "runtest cts-appsecurity".
5982 *
5983 * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
5984 * src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
5985 */
5986 public String getProviderMimeType(Uri uri) {
5987 final String name = uri.getAuthority();
5988 final long ident = Binder.clearCallingIdentity();
5989 ContentProviderHolder holder = null;
5990
5991 try {
5992 holder = getContentProviderExternal(name);
5993 if (holder != null) {
5994 return holder.provider.getType(uri);
5995 }
5996 } catch (RemoteException e) {
5997 Log.w(TAG, "Content provider dead retrieving " + uri, e);
5998 return null;
5999 } finally {
6000 if (holder != null) {
6001 removeContentProviderExternal(name);
6002 }
6003 Binder.restoreCallingIdentity(ident);
6004 }
6005
6006 return null;
6007 }
6008
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006009 // =========================================================
6010 // GLOBAL MANAGEMENT
6011 // =========================================================
6012
6013 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
6014 ApplicationInfo info, String customProcess) {
6015 String proc = customProcess != null ? customProcess : info.processName;
6016 BatteryStatsImpl.Uid.Proc ps = null;
6017 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
6018 synchronized (stats) {
6019 ps = stats.getProcessStatsLocked(info.uid, proc);
6020 }
6021 return new ProcessRecord(ps, thread, info, proc);
6022 }
6023
6024 final ProcessRecord addAppLocked(ApplicationInfo info) {
6025 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
6026
6027 if (app == null) {
6028 app = newProcessRecordLocked(null, info, null);
6029 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006030 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006031 }
6032
Dianne Hackborne7f97212011-02-24 14:40:20 -08006033 // This package really, really can not be stopped.
6034 try {
6035 AppGlobals.getPackageManager().setPackageStoppedState(
6036 info.packageName, false);
6037 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08006038 } catch (IllegalArgumentException e) {
6039 Slog.w(TAG, "Failed trying to unstop package "
6040 + info.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08006041 }
6042
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006043 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
6044 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
6045 app.persistent = true;
6046 app.maxAdj = CORE_SERVER_ADJ;
6047 }
6048 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
6049 mPersistentStartingProcesses.add(app);
6050 startProcessLocked(app, "added application", app.processName);
6051 }
6052
6053 return app;
6054 }
6055
6056 public void unhandledBack() {
6057 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
6058 "unhandledBack()");
6059
6060 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006061 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08006062 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006063 TAG, "Performing unhandledBack(): stack size = " + count);
6064 if (count > 1) {
6065 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006066 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006067 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
6068 Binder.restoreCallingIdentity(origId);
6069 }
6070 }
6071 }
6072
6073 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
6074 String name = uri.getAuthority();
6075 ContentProviderHolder cph = getContentProviderExternal(name);
6076 ParcelFileDescriptor pfd = null;
6077 if (cph != null) {
6078 // We record the binder invoker's uid in thread-local storage before
6079 // going to the content provider to open the file. Later, in the code
6080 // that handles all permissions checks, we look for this uid and use
6081 // that rather than the Activity Manager's own uid. The effect is that
6082 // we do the check against the caller's permissions even though it looks
6083 // to the content provider like the Activity Manager itself is making
6084 // the request.
6085 sCallerIdentity.set(new Identity(
6086 Binder.getCallingPid(), Binder.getCallingUid()));
6087 try {
6088 pfd = cph.provider.openFile(uri, "r");
6089 } catch (FileNotFoundException e) {
6090 // do nothing; pfd will be returned null
6091 } finally {
6092 // Ensure that whatever happens, we clean up the identity state
6093 sCallerIdentity.remove();
6094 }
6095
6096 // We've got the fd now, so we're done with the provider.
6097 removeContentProviderExternal(name);
6098 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006099 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006100 }
6101 return pfd;
6102 }
6103
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006104 // Actually is sleeping or shutting down or whatever else in the future
6105 // is an inactive state.
6106 public boolean isSleeping() {
6107 return mSleeping || mShuttingDown;
6108 }
6109
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006110 public void goingToSleep() {
6111 synchronized(this) {
6112 mSleeping = true;
6113 mWindowManager.setEventDispatching(false);
6114
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006115 mMainStack.stopIfSleepingLocked();
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07006116
6117 // Initialize the wake times of all processes.
Dianne Hackborn287952c2010-09-22 22:34:31 -07006118 checkExcessivePowerUsageLocked(false);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07006119 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
6120 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07006121 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006122 }
6123 }
6124
Dianne Hackborn55280a92009-05-07 15:53:46 -07006125 public boolean shutdown(int timeout) {
6126 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
6127 != PackageManager.PERMISSION_GRANTED) {
6128 throw new SecurityException("Requires permission "
6129 + android.Manifest.permission.SHUTDOWN);
6130 }
6131
6132 boolean timedout = false;
6133
6134 synchronized(this) {
6135 mShuttingDown = true;
6136 mWindowManager.setEventDispatching(false);
6137
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006138 if (mMainStack.mResumedActivity != null) {
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006139 mMainStack.stopIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07006140 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006141 while (mMainStack.mResumedActivity != null
6142 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07006143 long delay = endTime - System.currentTimeMillis();
6144 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006145 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07006146 timedout = true;
6147 break;
6148 }
6149 try {
6150 this.wait();
6151 } catch (InterruptedException e) {
6152 }
6153 }
6154 }
6155 }
6156
6157 mUsageStatsService.shutdown();
6158 mBatteryStatsService.shutdown();
6159
6160 return timedout;
6161 }
6162
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006163 public final void activitySlept(IBinder token) {
6164 if (localLOGV) Slog.v(
6165 TAG, "Activity slept: token=" + token);
6166
6167 ActivityRecord r = null;
6168
6169 final long origId = Binder.clearCallingIdentity();
6170
6171 synchronized (this) {
6172 int index = mMainStack.indexOfTokenLocked(token);
6173 if (index >= 0) {
6174 r = (ActivityRecord)mMainStack.mHistory.get(index);
6175 mMainStack.activitySleptLocked(r);
6176 }
6177 }
6178
6179 Binder.restoreCallingIdentity(origId);
6180 }
6181
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006182 public void wakingUp() {
6183 synchronized(this) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006184 mWindowManager.setEventDispatching(true);
6185 mSleeping = false;
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006186 mMainStack.awakeFromSleepingLocked();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006187 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006188 }
6189 }
6190
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006191 public void stopAppSwitches() {
6192 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
6193 != PackageManager.PERMISSION_GRANTED) {
6194 throw new SecurityException("Requires permission "
6195 + android.Manifest.permission.STOP_APP_SWITCHES);
6196 }
6197
6198 synchronized(this) {
6199 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
6200 + APP_SWITCH_DELAY_TIME;
6201 mDidAppSwitch = false;
6202 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
6203 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
6204 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
6205 }
6206 }
6207
6208 public void resumeAppSwitches() {
6209 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
6210 != PackageManager.PERMISSION_GRANTED) {
6211 throw new SecurityException("Requires permission "
6212 + android.Manifest.permission.STOP_APP_SWITCHES);
6213 }
6214
6215 synchronized(this) {
6216 // Note that we don't execute any pending app switches... we will
6217 // let those wait until either the timeout, or the next start
6218 // activity request.
6219 mAppSwitchesAllowedTime = 0;
6220 }
6221 }
6222
6223 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
6224 String name) {
6225 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
6226 return true;
6227 }
6228
6229 final int perm = checkComponentPermission(
6230 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08006231 callingUid, -1, true);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006232 if (perm == PackageManager.PERMISSION_GRANTED) {
6233 return true;
6234 }
6235
Joe Onorato8a9b2202010-02-26 18:56:32 -08006236 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006237 return false;
6238 }
6239
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006240 public void setDebugApp(String packageName, boolean waitForDebugger,
6241 boolean persistent) {
6242 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
6243 "setDebugApp()");
6244
6245 // Note that this is not really thread safe if there are multiple
6246 // callers into it at the same time, but that's not a situation we
6247 // care about.
6248 if (persistent) {
6249 final ContentResolver resolver = mContext.getContentResolver();
6250 Settings.System.putString(
6251 resolver, Settings.System.DEBUG_APP,
6252 packageName);
6253 Settings.System.putInt(
6254 resolver, Settings.System.WAIT_FOR_DEBUGGER,
6255 waitForDebugger ? 1 : 0);
6256 }
6257
6258 synchronized (this) {
6259 if (!persistent) {
6260 mOrigDebugApp = mDebugApp;
6261 mOrigWaitForDebugger = mWaitForDebugger;
6262 }
6263 mDebugApp = packageName;
6264 mWaitForDebugger = waitForDebugger;
6265 mDebugTransient = !persistent;
6266 if (packageName != null) {
6267 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006268 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006269 Binder.restoreCallingIdentity(origId);
6270 }
6271 }
6272 }
6273
6274 public void setAlwaysFinish(boolean enabled) {
6275 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
6276 "setAlwaysFinish()");
6277
6278 Settings.System.putInt(
6279 mContext.getContentResolver(),
6280 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
6281
6282 synchronized (this) {
6283 mAlwaysFinishActivities = enabled;
6284 }
6285 }
6286
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006287 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006288 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006289 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006290 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006291 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006292 }
6293 }
6294
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08006295 public boolean isUserAMonkey() {
6296 // For now the fact that there is a controller implies
6297 // we have a monkey.
6298 synchronized (this) {
6299 return mController != null;
6300 }
6301 }
6302
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006303 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06006304 synchronized (this) {
6305 mWatchers.register(watcher);
6306 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006307 }
6308
6309 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06006310 synchronized (this) {
6311 mWatchers.unregister(watcher);
6312 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006313 }
6314
Jeff Sharkeya4620792011-05-20 15:29:23 -07006315 public void registerProcessObserver(IProcessObserver observer) {
6316 mProcessObservers.register(observer);
6317 }
6318
6319 public void unregisterProcessObserver(IProcessObserver observer) {
6320 mProcessObservers.unregister(observer);
6321 }
6322
Daniel Sandler69a48172010-06-23 16:29:36 -04006323 public void setImmersive(IBinder token, boolean immersive) {
6324 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006325 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04006326 if (index < 0) {
6327 throw new IllegalArgumentException();
6328 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006329 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04006330 r.immersive = immersive;
6331 }
6332 }
6333
6334 public boolean isImmersive(IBinder token) {
6335 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006336 int index = (token != null) ? mMainStack.indexOfTokenLocked(token) : -1;
Daniel Sandler69a48172010-06-23 16:29:36 -04006337 if (index < 0) {
6338 throw new IllegalArgumentException();
6339 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006340 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(index);
Daniel Sandler69a48172010-06-23 16:29:36 -04006341 return r.immersive;
6342 }
6343 }
6344
6345 public boolean isTopActivityImmersive() {
6346 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006347 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Daniel Sandler69a48172010-06-23 16:29:36 -04006348 return (r != null) ? r.immersive : false;
6349 }
6350 }
6351
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006352 public final void enterSafeMode() {
6353 synchronized(this) {
6354 // It only makes sense to do this before the system is ready
6355 // and started launching other packages.
6356 if (!mSystemReady) {
6357 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006358 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006359 } catch (RemoteException e) {
6360 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006361 }
6362 }
6363 }
6364
Jeff Brownb09abc12011-01-13 21:08:27 -08006365 public final void showSafeModeOverlay() {
6366 View v = LayoutInflater.from(mContext).inflate(
6367 com.android.internal.R.layout.safe_mode, null);
6368 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
6369 lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
6370 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
6371 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
6372 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
6373 lp.format = v.getBackground().getOpacity();
6374 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
6375 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
6376 ((WindowManager)mContext.getSystemService(
6377 Context.WINDOW_SERVICE)).addView(v, lp);
6378 }
6379
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006380 public void noteWakeupAlarm(IIntentSender sender) {
6381 if (!(sender instanceof PendingIntentRecord)) {
6382 return;
6383 }
6384 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
6385 synchronized (stats) {
6386 if (mBatteryStatsService.isOnBattery()) {
6387 mBatteryStatsService.enforceCallingPermission();
6388 PendingIntentRecord rec = (PendingIntentRecord)sender;
6389 int MY_UID = Binder.getCallingUid();
6390 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
6391 BatteryStatsImpl.Uid.Pkg pkg =
6392 stats.getPackageStatsLocked(uid, rec.key.packageName);
6393 pkg.incWakeupsLocked();
6394 }
6395 }
6396 }
6397
Dianne Hackborn64825172011-03-02 21:32:58 -08006398 public boolean killPids(int[] pids, String pReason, boolean secure) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006399 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006400 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006401 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006402 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006403 // XXX Note: don't acquire main activity lock here, because the window
6404 // manager calls in with its locks held.
6405
6406 boolean killed = false;
6407 synchronized (mPidsSelfLocked) {
6408 int[] types = new int[pids.length];
6409 int worstType = 0;
6410 for (int i=0; i<pids.length; i++) {
6411 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6412 if (proc != null) {
6413 int type = proc.setAdj;
6414 types[i] = type;
6415 if (type > worstType) {
6416 worstType = type;
6417 }
6418 }
6419 }
6420
Dianne Hackborn64825172011-03-02 21:32:58 -08006421 // If the worst oom_adj is somewhere in the hidden proc LRU range,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006422 // then constrain it so we will kill all hidden procs.
6423 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
6424 worstType = HIDDEN_APP_MIN_ADJ;
6425 }
Dianne Hackborn64825172011-03-02 21:32:58 -08006426
6427 // If this is not a secure call, don't let it kill processes that
6428 // are important.
6429 if (!secure && worstType < SECONDARY_SERVER_ADJ) {
6430 worstType = SECONDARY_SERVER_ADJ;
6431 }
6432
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006433 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006434 for (int i=0; i<pids.length; i++) {
6435 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6436 if (proc == null) {
6437 continue;
6438 }
6439 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006440 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07006441 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006442 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
6443 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006444 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006445 proc.killedBackground = true;
6446 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006447 }
6448 }
6449 }
6450 return killed;
6451 }
6452
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006453 public final void startRunning(String pkg, String cls, String action,
6454 String data) {
6455 synchronized(this) {
6456 if (mStartRunning) {
6457 return;
6458 }
6459 mStartRunning = true;
6460 mTopComponent = pkg != null && cls != null
6461 ? new ComponentName(pkg, cls) : null;
6462 mTopAction = action != null ? action : Intent.ACTION_MAIN;
6463 mTopData = data;
6464 if (!mSystemReady) {
6465 return;
6466 }
6467 }
6468
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006469 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006470 }
6471
6472 private void retrieveSettings() {
6473 final ContentResolver resolver = mContext.getContentResolver();
6474 String debugApp = Settings.System.getString(
6475 resolver, Settings.System.DEBUG_APP);
6476 boolean waitForDebugger = Settings.System.getInt(
6477 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
6478 boolean alwaysFinishActivities = Settings.System.getInt(
6479 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
6480
6481 Configuration configuration = new Configuration();
6482 Settings.System.getConfiguration(resolver, configuration);
6483
6484 synchronized (this) {
6485 mDebugApp = mOrigDebugApp = debugApp;
6486 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
6487 mAlwaysFinishActivities = alwaysFinishActivities;
6488 // This happens before any activities are started, so we can
6489 // change mConfiguration in-place.
6490 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08006491 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006492 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006493 }
6494 }
6495
6496 public boolean testIsSystemReady() {
6497 // no need to synchronize(this) just to read & return the value
6498 return mSystemReady;
6499 }
6500
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006501 private static File getCalledPreBootReceiversFile() {
6502 File dataDir = Environment.getDataDirectory();
6503 File systemDir = new File(dataDir, "system");
6504 File fname = new File(systemDir, "called_pre_boots.dat");
6505 return fname;
6506 }
6507
6508 private static ArrayList<ComponentName> readLastDonePreBootReceivers() {
6509 ArrayList<ComponentName> lastDoneReceivers = new ArrayList<ComponentName>();
6510 File file = getCalledPreBootReceiversFile();
6511 FileInputStream fis = null;
6512 try {
6513 fis = new FileInputStream(file);
6514 DataInputStream dis = new DataInputStream(new BufferedInputStream(fis, 2048));
6515 int vers = dis.readInt();
6516 String codename = dis.readUTF();
6517 if (vers == android.os.Build.VERSION.SDK_INT
6518 && codename.equals(android.os.Build.VERSION.CODENAME)) {
6519 int num = dis.readInt();
6520 while (num > 0) {
6521 num--;
6522 String pkg = dis.readUTF();
6523 String cls = dis.readUTF();
6524 lastDoneReceivers.add(new ComponentName(pkg, cls));
6525 }
6526 }
6527 } catch (FileNotFoundException e) {
6528 } catch (IOException e) {
6529 Slog.w(TAG, "Failure reading last done pre-boot receivers", e);
6530 } finally {
6531 if (fis != null) {
6532 try {
6533 fis.close();
6534 } catch (IOException e) {
6535 }
6536 }
6537 }
6538 return lastDoneReceivers;
6539 }
6540
6541 private static void writeLastDonePreBootReceivers(ArrayList<ComponentName> list) {
6542 File file = getCalledPreBootReceiversFile();
6543 FileOutputStream fos = null;
6544 DataOutputStream dos = null;
6545 try {
6546 Slog.i(TAG, "Writing new set of last done pre-boot receivers...");
6547 fos = new FileOutputStream(file);
6548 dos = new DataOutputStream(new BufferedOutputStream(fos, 2048));
6549 dos.writeInt(android.os.Build.VERSION.SDK_INT);
6550 dos.writeUTF(android.os.Build.VERSION.CODENAME);
6551 dos.writeInt(list.size());
6552 for (int i=0; i<list.size(); i++) {
6553 dos.writeUTF(list.get(i).getPackageName());
6554 dos.writeUTF(list.get(i).getClassName());
6555 }
6556 } catch (IOException e) {
6557 Slog.w(TAG, "Failure writing last done pre-boot receivers", e);
6558 file.delete();
6559 } finally {
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07006560 FileUtils.sync(fos);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006561 if (dos != null) {
6562 try {
6563 dos.close();
6564 } catch (IOException e) {
6565 // TODO Auto-generated catch block
6566 e.printStackTrace();
6567 }
6568 }
6569 }
6570 }
6571
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006572 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006573 synchronized(this) {
6574 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006575 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006576 return;
6577 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006578
6579 // Check to see if there are any update receivers to run.
6580 if (!mDidUpdate) {
6581 if (mWaitingUpdate) {
6582 return;
6583 }
6584 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
6585 List<ResolveInfo> ris = null;
6586 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006587 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006588 intent, null, 0);
6589 } catch (RemoteException e) {
6590 }
6591 if (ris != null) {
6592 for (int i=ris.size()-1; i>=0; i--) {
6593 if ((ris.get(i).activityInfo.applicationInfo.flags
6594 &ApplicationInfo.FLAG_SYSTEM) == 0) {
6595 ris.remove(i);
6596 }
6597 }
6598 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006599
6600 ArrayList<ComponentName> lastDoneReceivers = readLastDonePreBootReceivers();
6601
6602 final ArrayList<ComponentName> doneReceivers = new ArrayList<ComponentName>();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006603 for (int i=0; i<ris.size(); i++) {
6604 ActivityInfo ai = ris.get(i).activityInfo;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006605 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6606 if (lastDoneReceivers.contains(comp)) {
6607 ris.remove(i);
6608 i--;
6609 }
6610 }
6611
6612 for (int i=0; i<ris.size(); i++) {
6613 ActivityInfo ai = ris.get(i).activityInfo;
6614 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6615 doneReceivers.add(comp);
6616 intent.setComponent(comp);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006617 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08006618 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006619 finisher = new IIntentReceiver.Stub() {
6620 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07006621 String data, Bundle extras, boolean ordered,
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006622 boolean sticky) {
6623 // The raw IIntentReceiver interface is called
6624 // with the AM lock held, so redispatch to
6625 // execute our code without the lock.
6626 mHandler.post(new Runnable() {
6627 public void run() {
6628 synchronized (ActivityManagerService.this) {
6629 mDidUpdate = true;
6630 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006631 writeLastDonePreBootReceivers(doneReceivers);
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006632 systemReady(goingCallback);
6633 }
6634 });
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006635 }
6636 };
6637 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006638 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006639 broadcastIntentLocked(null, null, intent, null, finisher,
6640 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08006641 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006642 mWaitingUpdate = true;
6643 }
6644 }
6645 }
6646 if (mWaitingUpdate) {
6647 return;
6648 }
6649 mDidUpdate = true;
6650 }
6651
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006652 mSystemReady = true;
6653 if (!mStartRunning) {
6654 return;
6655 }
6656 }
6657
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006658 ArrayList<ProcessRecord> procsToKill = null;
6659 synchronized(mPidsSelfLocked) {
6660 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
6661 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
6662 if (!isAllowedWhileBooting(proc.info)){
6663 if (procsToKill == null) {
6664 procsToKill = new ArrayList<ProcessRecord>();
6665 }
6666 procsToKill.add(proc);
6667 }
6668 }
6669 }
6670
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006671 synchronized(this) {
6672 if (procsToKill != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006673 for (int i=procsToKill.size()-1; i>=0; i--) {
6674 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08006675 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006676 removeProcessLocked(proc, true);
6677 }
6678 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006679
6680 // Now that we have cleaned up any update processes, we
6681 // are ready to start launching real processes and know that
6682 // we won't trample on them any more.
6683 mProcessesReady = true;
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006684 }
6685
Joe Onorato8a9b2202010-02-26 18:56:32 -08006686 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006687 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006688 SystemClock.uptimeMillis());
6689
6690 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006691 // Make sure we have no pre-ready processes sitting around.
6692
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006693 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
6694 ResolveInfo ri = mContext.getPackageManager()
6695 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07006696 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006697 CharSequence errorMsg = null;
6698 if (ri != null) {
6699 ActivityInfo ai = ri.activityInfo;
6700 ApplicationInfo app = ai.applicationInfo;
6701 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
6702 mTopAction = Intent.ACTION_FACTORY_TEST;
6703 mTopData = null;
6704 mTopComponent = new ComponentName(app.packageName,
6705 ai.name);
6706 } else {
6707 errorMsg = mContext.getResources().getText(
6708 com.android.internal.R.string.factorytest_not_system);
6709 }
6710 } else {
6711 errorMsg = mContext.getResources().getText(
6712 com.android.internal.R.string.factorytest_no_action);
6713 }
6714 if (errorMsg != null) {
6715 mTopAction = null;
6716 mTopData = null;
6717 mTopComponent = null;
6718 Message msg = Message.obtain();
6719 msg.what = SHOW_FACTORY_ERROR_MSG;
6720 msg.getData().putCharSequence("msg", errorMsg);
6721 mHandler.sendMessage(msg);
6722 }
6723 }
6724 }
6725
6726 retrieveSettings();
6727
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006728 if (goingCallback != null) goingCallback.run();
6729
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006730 synchronized (this) {
6731 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
6732 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006733 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07006734 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006735 if (apps != null) {
6736 int N = apps.size();
6737 int i;
6738 for (i=0; i<N; i++) {
6739 ApplicationInfo info
6740 = (ApplicationInfo)apps.get(i);
6741 if (info != null &&
6742 !info.packageName.equals("android")) {
6743 addAppLocked(info);
6744 }
6745 }
6746 }
6747 } catch (RemoteException ex) {
6748 // pm is in same process, this will never happen.
6749 }
6750 }
6751
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006752 // Start up initial activity.
6753 mBooting = true;
6754
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006755 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006756 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006757 Message msg = Message.obtain();
6758 msg.what = SHOW_UID_ERROR_MSG;
6759 mHandler.sendMessage(msg);
6760 }
6761 } catch (RemoteException e) {
6762 }
6763
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006764 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006765 }
6766 }
6767
Dan Egnorb7f03672009-12-09 16:22:32 -08006768 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006769 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006770 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006771 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006772 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006773 startAppProblemLocked(app);
6774 app.stopFreezingAllLocked();
6775 return handleAppCrashLocked(app);
6776 }
6777
Dan Egnorb7f03672009-12-09 16:22:32 -08006778 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006779 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006780 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006781 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006782 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
6783 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006784 startAppProblemLocked(app);
6785 app.stopFreezingAllLocked();
6786 }
6787
6788 /**
6789 * Generate a process error record, suitable for attachment to a ProcessRecord.
6790 *
6791 * @param app The ProcessRecord in which the error occurred.
6792 * @param condition Crashing, Application Not Responding, etc. Values are defined in
6793 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08006794 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006795 * @param shortMsg Short message describing the crash.
6796 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08006797 * @param stackTrace Full crash stack trace, may be null.
6798 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006799 * @return Returns a fully-formed AppErrorStateInfo record.
6800 */
6801 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006802 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006803 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08006804
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006805 report.condition = condition;
6806 report.processName = app.processName;
6807 report.pid = app.pid;
6808 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08006809 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006810 report.shortMsg = shortMsg;
6811 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08006812 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006813
6814 return report;
6815 }
6816
Dan Egnor42471dd2010-01-07 17:25:22 -08006817 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006818 synchronized (this) {
6819 app.crashing = false;
6820 app.crashingReport = null;
6821 app.notResponding = false;
6822 app.notRespondingReport = null;
6823 if (app.anrDialog == fromDialog) {
6824 app.anrDialog = null;
6825 }
6826 if (app.waitDialog == fromDialog) {
6827 app.waitDialog = null;
6828 }
6829 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08006830 handleAppCrashLocked(app);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07006831 Slog.i(ActivityManagerService.TAG, "Killing " + app + ": user's request");
Dianne Hackborn8633e682010-04-22 16:03:41 -07006832 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
6833 app.processName, app.setAdj, "user's request after error");
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07006834 Process.killProcessQuiet(app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006835 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006836 }
6837 }
Dan Egnor42471dd2010-01-07 17:25:22 -08006838
Dan Egnorb7f03672009-12-09 16:22:32 -08006839 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006840 long now = SystemClock.uptimeMillis();
6841
6842 Long crashTime = mProcessCrashTimes.get(app.info.processName,
6843 app.info.uid);
6844 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
6845 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006846 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006847 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006848 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006849 app.info.processName, app.info.uid);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006850 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
6851 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006852 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006853 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006854 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006855 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006856 }
6857 }
6858 if (!app.persistent) {
Dianne Hackborn070783f2010-12-29 16:46:28 -08006859 // Don't let services in this process be restarted and potentially
6860 // annoy the user repeatedly. Unless it is persistent, since those
6861 // processes run critical code.
6862 killServicesLocked(app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006863 // We don't want to start this process again until the user
6864 // explicitly does so... but for persistent process, we really
6865 // need to keep it running. If a persistent process is actually
6866 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08006867 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006868 app.info.processName);
6869 mBadProcesses.put(app.info.processName, app.info.uid, now);
6870 app.bad = true;
6871 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
6872 app.removed = true;
6873 removeProcessLocked(app, false);
Dianne Hackborncb44d962011-03-10 17:02:27 -08006874 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006875 return false;
6876 }
Dianne Hackborncb44d962011-03-10 17:02:27 -08006877 mMainStack.resumeTopActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006878 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006879 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006880 if (r.app == app) {
6881 // If the top running activity is from this crashing
6882 // process, then terminate it to avoid getting in a loop.
6883 Slog.w(TAG, " Force finishing activity "
6884 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006885 int index = mMainStack.indexOfTokenLocked(r);
6886 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006887 Activity.RESULT_CANCELED, null, "crashed");
Dianne Hackborn070783f2010-12-29 16:46:28 -08006888 // Also terminate any activities below it that aren't yet
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006889 // stopped, to avoid a situation where one will get
6890 // re-start our crashing activity once it gets resumed again.
6891 index--;
6892 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006893 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006894 if (r.state == ActivityState.RESUMED
6895 || r.state == ActivityState.PAUSING
6896 || r.state == ActivityState.PAUSED) {
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -08006897 if (!r.isHomeActivity || mHomeProcess != r.app) {
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006898 Slog.w(TAG, " Force finishing activity "
6899 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006900 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006901 Activity.RESULT_CANCELED, null, "crashed");
6902 }
6903 }
6904 }
6905 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006906 }
6907
6908 // Bump up the crash count of any services currently running in the proc.
6909 if (app.services.size() != 0) {
6910 // Any services running in the application need to be placed
6911 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07006912 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006913 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006914 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006915 sr.crashCount++;
6916 }
6917 }
Mattias Larssona4fd0072010-06-22 22:37:03 +02006918
6919 // If the crashing process is what we consider to be the "home process" and it has been
6920 // replaced by a third-party app, clear the package preferred activities from packages
6921 // with a home activity running in the process to prevent a repeatedly crashing app
6922 // from blocking the user to manually clear the list.
6923 if (app == mHomeProcess && mHomeProcess.activities.size() > 0
6924 && (mHomeProcess.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
6925 Iterator it = mHomeProcess.activities.iterator();
6926 while (it.hasNext()) {
Jean-Baptiste Queru5ea89f72010-07-30 09:30:31 -07006927 ActivityRecord r = (ActivityRecord)it.next();
Mattias Larssona4fd0072010-06-22 22:37:03 +02006928 if (r.isHomeActivity) {
6929 Log.i(TAG, "Clearing package preferred activities from " + r.packageName);
6930 try {
6931 ActivityThread.getPackageManager()
6932 .clearPackagePreferredActivities(r.packageName);
6933 } catch (RemoteException c) {
6934 // pm is in same process, this will never happen.
6935 }
6936 }
6937 }
6938 }
6939
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006940 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
6941 return true;
6942 }
6943
6944 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006945 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
6946 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006947 skipCurrentReceiverLocked(app);
6948 }
6949
6950 void skipCurrentReceiverLocked(ProcessRecord app) {
6951 boolean reschedule = false;
6952 BroadcastRecord r = app.curReceiver;
6953 if (r != null) {
6954 // The current broadcast is waiting for this app's receiver
6955 // to be finished. Looks like that's not going to happen, so
6956 // let the broadcast continue.
Jeff Brown4d94a762010-09-23 11:33:28 -07006957 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006958 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6959 r.resultExtras, r.resultAbort, true);
6960 reschedule = true;
6961 }
6962 r = mPendingBroadcast;
6963 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006964 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006965 "skip & discard pending app " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -07006966 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006967 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6968 r.resultExtras, r.resultAbort, true);
6969 reschedule = true;
6970 }
6971 if (reschedule) {
6972 scheduleBroadcastsLocked();
6973 }
6974 }
6975
Dan Egnor60d87622009-12-16 16:32:58 -08006976 /**
6977 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
6978 * The application process will exit immediately after this call returns.
6979 * @param app object of the crashing app, null for the system server
6980 * @param crashInfo describing the exception
6981 */
6982 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
Dianne Hackborncb44d962011-03-10 17:02:27 -08006983 ProcessRecord r = findAppProcess(app, "Crash");
Dan Egnor60d87622009-12-16 16:32:58 -08006984
6985 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
6986 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006987 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006988 crashInfo.exceptionClassName,
6989 crashInfo.exceptionMessage,
6990 crashInfo.throwFileName,
6991 crashInfo.throwLineNumber);
6992
Dan Egnor42471dd2010-01-07 17:25:22 -08006993 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006994
6995 crashApplication(r, crashInfo);
6996 }
6997
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006998 public void handleApplicationStrictModeViolation(
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006999 IBinder app,
7000 int violationMask,
7001 StrictMode.ViolationInfo info) {
Dianne Hackborncb44d962011-03-10 17:02:27 -08007002 ProcessRecord r = findAppProcess(app, "StrictMode");
7003 if (r == null) {
7004 return;
7005 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07007006
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07007007 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -08007008 Integer stackFingerprint = info.hashCode();
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07007009 boolean logIt = true;
7010 synchronized (mAlreadyLoggedViolatedStacks) {
7011 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
7012 logIt = false;
7013 // TODO: sub-sample into EventLog for these, with
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007014 // the info.durationMillis? Then we'd get
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07007015 // the relative pain numbers, without logging all
7016 // the stack traces repeatedly. We'd want to do
7017 // likewise in the client code, which also does
7018 // dup suppression, before the Binder call.
7019 } else {
7020 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
7021 mAlreadyLoggedViolatedStacks.clear();
7022 }
7023 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
7024 }
7025 }
7026 if (logIt) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007027 logStrictModeViolationToDropBox(r, info);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07007028 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07007029 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07007030
7031 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
7032 AppErrorResult result = new AppErrorResult();
7033 synchronized (this) {
7034 final long origId = Binder.clearCallingIdentity();
7035
7036 Message msg = Message.obtain();
7037 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
7038 HashMap<String, Object> data = new HashMap<String, Object>();
7039 data.put("result", result);
7040 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07007041 data.put("violationMask", violationMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007042 data.put("info", info);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07007043 msg.obj = data;
7044 mHandler.sendMessage(msg);
7045
7046 Binder.restoreCallingIdentity(origId);
7047 }
7048 int res = result.get();
Dianne Hackbornb424b632010-08-18 15:59:05 -07007049 Slog.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07007050 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07007051 }
7052
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007053 // Depending on the policy in effect, there could be a bunch of
7054 // these in quick succession so we try to batch these together to
7055 // minimize disk writes, number of dropbox entries, and maximize
7056 // compression, by having more fewer, larger records.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007057 private void logStrictModeViolationToDropBox(
7058 ProcessRecord process,
7059 StrictMode.ViolationInfo info) {
7060 if (info == null) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007061 return;
7062 }
7063 final boolean isSystemApp = process == null ||
7064 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
7065 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
7066 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
7067 final DropBoxManager dbox = (DropBoxManager)
7068 mContext.getSystemService(Context.DROPBOX_SERVICE);
7069
7070 // Exit early if the dropbox isn't configured to accept this report type.
7071 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
7072
7073 boolean bufferWasEmpty;
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007074 boolean needsFlush;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007075 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
7076 synchronized (sb) {
7077 bufferWasEmpty = sb.length() == 0;
7078 appendDropBoxProcessHeaders(process, sb);
7079 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
7080 sb.append("System-App: ").append(isSystemApp).append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007081 sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
7082 if (info.violationNumThisLoop != 0) {
7083 sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
7084 }
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07007085 if (info.numAnimationsRunning != 0) {
7086 sb.append("Animations-Running: ").append(info.numAnimationsRunning).append("\n");
7087 }
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07007088 if (info.broadcastIntentAction != null) {
7089 sb.append("Broadcast-Intent-Action: ").append(info.broadcastIntentAction).append("\n");
7090 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08007091 if (info.durationMillis != -1) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007092 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007093 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08007094 if (info.numInstances != -1) {
7095 sb.append("Instance-Count: ").append(info.numInstances).append("\n");
7096 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08007097 if (info.tags != null) {
7098 for (String tag : info.tags) {
7099 sb.append("Span-Tag: ").append(tag).append("\n");
7100 }
7101 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007102 sb.append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007103 if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
7104 sb.append(info.crashInfo.stackTrace);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007105 }
7106 sb.append("\n");
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007107
7108 // Only buffer up to ~64k. Various logging bits truncate
7109 // things at 128k.
7110 needsFlush = (sb.length() > 64 * 1024);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007111 }
7112
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007113 // Flush immediately if the buffer's grown too large, or this
7114 // is a non-system app. Non-system apps are isolated with a
7115 // different tag & policy and not batched.
7116 //
7117 // Batching is useful during internal testing with
7118 // StrictMode settings turned up high. Without batching,
7119 // thousands of separate files could be created on boot.
7120 if (!isSystemApp || needsFlush) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007121 new Thread("Error dump: " + dropboxTag) {
7122 @Override
7123 public void run() {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007124 String report;
7125 synchronized (sb) {
7126 report = sb.toString();
7127 sb.delete(0, sb.length());
7128 sb.trimToSize();
7129 }
7130 if (report.length() != 0) {
7131 dbox.addText(dropboxTag, report);
7132 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007133 }
7134 }.start();
7135 return;
7136 }
7137
7138 // System app batching:
7139 if (!bufferWasEmpty) {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007140 // An existing dropbox-writing thread is outstanding, so
7141 // we don't need to start it up. The existing thread will
7142 // catch the buffer appends we just did.
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007143 return;
7144 }
7145
7146 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
7147 // (After this point, we shouldn't access AMS internal data structures.)
7148 new Thread("Error dump: " + dropboxTag) {
7149 @Override
7150 public void run() {
7151 // 5 second sleep to let stacks arrive and be batched together
7152 try {
7153 Thread.sleep(5000); // 5 seconds
7154 } catch (InterruptedException e) {}
7155
7156 String errorReport;
7157 synchronized (mStrictModeBuffer) {
7158 errorReport = mStrictModeBuffer.toString();
7159 if (errorReport.length() == 0) {
7160 return;
7161 }
7162 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
7163 mStrictModeBuffer.trimToSize();
7164 }
7165 dbox.addText(dropboxTag, errorReport);
7166 }
7167 }.start();
7168 }
7169
Dan Egnor60d87622009-12-16 16:32:58 -08007170 /**
7171 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
7172 * @param app object of the crashing app, null for the system server
7173 * @param tag reported by the caller
7174 * @param crashInfo describing the context of the error
7175 * @return true if the process should exit immediately (WTF is fatal)
7176 */
7177 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08007178 ApplicationErrorReport.CrashInfo crashInfo) {
Dianne Hackborncb44d962011-03-10 17:02:27 -08007179 ProcessRecord r = findAppProcess(app, "WTF");
Dan Egnor60d87622009-12-16 16:32:58 -08007180
7181 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
7182 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08007183 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08007184 tag, crashInfo.exceptionMessage);
7185
Dan Egnor42471dd2010-01-07 17:25:22 -08007186 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08007187
Dianne Hackborn1ab43772011-03-15 14:38:02 -07007188 if (r != null && r.pid != Process.myPid() &&
7189 Settings.Secure.getInt(mContext.getContentResolver(),
7190 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08007191 crashApplication(r, crashInfo);
7192 return true;
7193 } else {
7194 return false;
7195 }
7196 }
7197
7198 /**
7199 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
7200 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
7201 */
Dianne Hackborncb44d962011-03-10 17:02:27 -08007202 private ProcessRecord findAppProcess(IBinder app, String reason) {
Dan Egnor60d87622009-12-16 16:32:58 -08007203 if (app == null) {
7204 return null;
7205 }
7206
7207 synchronized (this) {
7208 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
7209 final int NA = apps.size();
7210 for (int ia=0; ia<NA; ia++) {
7211 ProcessRecord p = apps.valueAt(ia);
7212 if (p.thread != null && p.thread.asBinder() == app) {
7213 return p;
7214 }
7215 }
7216 }
7217
Dianne Hackborncb44d962011-03-10 17:02:27 -08007218 Slog.w(TAG, "Can't find mystery application for " + reason
7219 + " from pid=" + Binder.getCallingPid()
7220 + " uid=" + Binder.getCallingUid() + ": " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08007221 return null;
7222 }
7223 }
7224
7225 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007226 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
7227 * to append various headers to the dropbox log text.
Dan Egnor60d87622009-12-16 16:32:58 -08007228 */
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07007229 private void appendDropBoxProcessHeaders(ProcessRecord process, StringBuilder sb) {
Vairavan Srinivasan68a4e0a2011-02-14 20:45:59 -08007230 // Watchdog thread ends up invoking this function (with
7231 // a null ProcessRecord) to add the stack file to dropbox.
7232 // Do not acquire a lock on this (am) in such cases, as it
7233 // could cause a potential deadlock, if and when watchdog
7234 // is invoked due to unavailability of lock on am and it
7235 // would prevent watchdog from killing system_server.
7236 if (process == null) {
7237 sb.append("Process: system_server\n");
7238 return;
7239 }
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07007240 // Note: ProcessRecord 'process' is guarded by the service
7241 // instance. (notably process.pkgList, which could otherwise change
7242 // concurrently during execution of this method)
7243 synchronized (this) {
Vairavan Srinivasan68a4e0a2011-02-14 20:45:59 -08007244 if (process.pid == MY_PID) {
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07007245 sb.append("Process: system_server\n");
7246 } else {
7247 sb.append("Process: ").append(process.processName).append("\n");
7248 }
Dan Egnora455d192010-03-12 08:52:28 -08007249 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007250 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08007251 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
7252 for (String pkg : process.pkgList) {
7253 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08007254 try {
Dan Egnora455d192010-03-12 08:52:28 -08007255 PackageInfo pi = pm.getPackageInfo(pkg, 0);
7256 if (pi != null) {
7257 sb.append(" v").append(pi.versionCode);
7258 if (pi.versionName != null) {
7259 sb.append(" (").append(pi.versionName).append(")");
7260 }
7261 }
7262 } catch (RemoteException e) {
7263 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08007264 }
Dan Egnora455d192010-03-12 08:52:28 -08007265 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08007266 }
Dan Egnora455d192010-03-12 08:52:28 -08007267 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007268 }
7269
7270 private static String processClass(ProcessRecord process) {
7271 if (process == null || process.pid == MY_PID) {
7272 return "system_server";
7273 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
7274 return "system_app";
7275 } else {
7276 return "data_app";
7277 }
7278 }
7279
7280 /**
7281 * Write a description of an error (crash, WTF, ANR) to the drop box.
7282 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
7283 * @param process which caused the error, null means the system server
7284 * @param activity which triggered the error, null if unknown
7285 * @param parent activity related to the error, null if unknown
7286 * @param subject line related to the error, null if absent
7287 * @param report in long form describing the error, null if absent
7288 * @param logFile to include in the report, null if none
7289 * @param crashInfo giving an application stack trace, null if absent
7290 */
7291 public void addErrorToDropBox(String eventType,
7292 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
7293 final String report, final File logFile,
7294 final ApplicationErrorReport.CrashInfo crashInfo) {
7295 // NOTE -- this must never acquire the ActivityManagerService lock,
7296 // otherwise the watchdog may be prevented from resetting the system.
7297
7298 final String dropboxTag = processClass(process) + "_" + eventType;
7299 final DropBoxManager dbox = (DropBoxManager)
7300 mContext.getSystemService(Context.DROPBOX_SERVICE);
7301
7302 // Exit early if the dropbox isn't configured to accept this report type.
7303 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
7304
7305 final StringBuilder sb = new StringBuilder(1024);
7306 appendDropBoxProcessHeaders(process, sb);
Dan Egnora455d192010-03-12 08:52:28 -08007307 if (activity != null) {
7308 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
7309 }
7310 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
7311 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
7312 }
7313 if (parent != null && parent != activity) {
7314 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
7315 }
7316 if (subject != null) {
7317 sb.append("Subject: ").append(subject).append("\n");
7318 }
7319 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
Christian Lindeberg03d2ca62010-09-28 14:52:20 +02007320 if (Debug.isDebuggerConnected()) {
7321 sb.append("Debugger: Connected\n");
7322 }
Dan Egnora455d192010-03-12 08:52:28 -08007323 sb.append("\n");
7324
7325 // Do the rest in a worker thread to avoid blocking the caller on I/O
7326 // (After this point, we shouldn't access AMS internal data structures.)
7327 Thread worker = new Thread("Error dump: " + dropboxTag) {
7328 @Override
7329 public void run() {
7330 if (report != null) {
7331 sb.append(report);
7332 }
7333 if (logFile != null) {
7334 try {
7335 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
7336 } catch (IOException e) {
7337 Slog.e(TAG, "Error reading " + logFile, e);
7338 }
7339 }
7340 if (crashInfo != null && crashInfo.stackTrace != null) {
7341 sb.append(crashInfo.stackTrace);
7342 }
7343
7344 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
7345 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
7346 if (lines > 0) {
7347 sb.append("\n");
7348
7349 // Merge several logcat streams, and take the last N lines
7350 InputStreamReader input = null;
7351 try {
7352 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
7353 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
7354 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
7355
7356 try { logcat.getOutputStream().close(); } catch (IOException e) {}
7357 try { logcat.getErrorStream().close(); } catch (IOException e) {}
7358 input = new InputStreamReader(logcat.getInputStream());
7359
7360 int num;
7361 char[] buf = new char[8192];
7362 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
7363 } catch (IOException e) {
7364 Slog.e(TAG, "Error running logcat", e);
7365 } finally {
7366 if (input != null) try { input.close(); } catch (IOException e) {}
7367 }
7368 }
7369
7370 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08007371 }
Dan Egnora455d192010-03-12 08:52:28 -08007372 };
7373
7374 if (process == null || process.pid == MY_PID) {
7375 worker.run(); // We may be about to die -- need to run this synchronously
7376 } else {
7377 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08007378 }
7379 }
7380
7381 /**
7382 * Bring up the "unexpected error" dialog box for a crashing app.
7383 * Deal with edge cases (intercepts from instrumented applications,
7384 * ActivityController, error intent receivers, that sort of thing).
7385 * @param r the application crashing
7386 * @param crashInfo describing the failure
7387 */
7388 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007389 long timeMillis = System.currentTimeMillis();
7390 String shortMsg = crashInfo.exceptionClassName;
7391 String longMsg = crashInfo.exceptionMessage;
7392 String stackTrace = crashInfo.stackTrace;
7393 if (shortMsg != null && longMsg != null) {
7394 longMsg = shortMsg + ": " + longMsg;
7395 } else if (shortMsg != null) {
7396 longMsg = shortMsg;
7397 }
7398
Dan Egnor60d87622009-12-16 16:32:58 -08007399 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007400 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007401 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007402 try {
7403 String name = r != null ? r.processName : null;
7404 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08007405 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08007406 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007407 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007408 + " at watcher's request");
7409 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08007410 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007411 }
7412 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007413 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007414 }
7415 }
7416
7417 final long origId = Binder.clearCallingIdentity();
7418
7419 // If this process is running instrumentation, finish it.
7420 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007421 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007422 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08007423 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
7424 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007425 Bundle info = new Bundle();
7426 info.putString("shortMsg", shortMsg);
7427 info.putString("longMsg", longMsg);
7428 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
7429 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007430 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007431 }
7432
Dan Egnor60d87622009-12-16 16:32:58 -08007433 // If we can't identify the process or it's already exceeded its crash quota,
7434 // quit right away without showing a crash dialog.
7435 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007436 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007437 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007438 }
7439
7440 Message msg = Message.obtain();
7441 msg.what = SHOW_ERROR_MSG;
7442 HashMap data = new HashMap();
7443 data.put("result", result);
7444 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007445 msg.obj = data;
7446 mHandler.sendMessage(msg);
7447
7448 Binder.restoreCallingIdentity(origId);
7449 }
7450
7451 int res = result.get();
7452
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007453 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007454 synchronized (this) {
7455 if (r != null) {
7456 mProcessCrashTimes.put(r.info.processName, r.info.uid,
7457 SystemClock.uptimeMillis());
7458 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007459 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007460 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007461 }
7462 }
7463
7464 if (appErrorIntent != null) {
7465 try {
7466 mContext.startActivity(appErrorIntent);
7467 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007468 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007469 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007470 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007471 }
Dan Egnorb7f03672009-12-09 16:22:32 -08007472
7473 Intent createAppErrorIntentLocked(ProcessRecord r,
7474 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
7475 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007476 if (report == null) {
7477 return null;
7478 }
7479 Intent result = new Intent(Intent.ACTION_APP_ERROR);
7480 result.setComponent(r.errorReportReceiver);
7481 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
7482 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
7483 return result;
7484 }
7485
Dan Egnorb7f03672009-12-09 16:22:32 -08007486 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
7487 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007488 if (r.errorReportReceiver == null) {
7489 return null;
7490 }
7491
7492 if (!r.crashing && !r.notResponding) {
7493 return null;
7494 }
7495
Dan Egnorb7f03672009-12-09 16:22:32 -08007496 ApplicationErrorReport report = new ApplicationErrorReport();
7497 report.packageName = r.info.packageName;
7498 report.installerPackageName = r.errorReportReceiver.getPackageName();
7499 report.processName = r.processName;
7500 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01007501 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007502
Dan Egnorb7f03672009-12-09 16:22:32 -08007503 if (r.crashing) {
7504 report.type = ApplicationErrorReport.TYPE_CRASH;
7505 report.crashInfo = crashInfo;
7506 } else if (r.notResponding) {
7507 report.type = ApplicationErrorReport.TYPE_ANR;
7508 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007509
Dan Egnorb7f03672009-12-09 16:22:32 -08007510 report.anrInfo.activity = r.notRespondingReport.tag;
7511 report.anrInfo.cause = r.notRespondingReport.shortMsg;
7512 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007513 }
7514
Dan Egnorb7f03672009-12-09 16:22:32 -08007515 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007516 }
7517
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007518 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
7519 // assume our apps are happy - lazy create the list
7520 List<ActivityManager.ProcessErrorStateInfo> errList = null;
7521
7522 synchronized (this) {
7523
7524 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007525 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7526 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007527 if ((app.thread != null) && (app.crashing || app.notResponding)) {
7528 // This one's in trouble, so we'll generate a report for it
7529 // crashes are higher priority (in case there's a crash *and* an anr)
7530 ActivityManager.ProcessErrorStateInfo report = null;
7531 if (app.crashing) {
7532 report = app.crashingReport;
7533 } else if (app.notResponding) {
7534 report = app.notRespondingReport;
7535 }
7536
7537 if (report != null) {
7538 if (errList == null) {
7539 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
7540 }
7541 errList.add(report);
7542 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007543 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007544 " crashing = " + app.crashing +
7545 " notResponding = " + app.notResponding);
7546 }
7547 }
7548 }
7549 }
7550
7551 return errList;
7552 }
7553
7554 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
7555 // Lazy instantiation of list
7556 List<ActivityManager.RunningAppProcessInfo> runList = null;
7557 synchronized (this) {
7558 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007559 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7560 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007561 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
7562 // Generate process state info for running application
7563 ActivityManager.RunningAppProcessInfo currApp =
7564 new ActivityManager.RunningAppProcessInfo(app.processName,
7565 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07007566 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007567 if (mHeavyWeightProcess == app) {
Dianne Hackborn482566e2010-09-03 12:51:28 -07007568 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007569 }
Dianne Hackborn42499172010-10-15 18:45:07 -07007570 if (app.persistent) {
7571 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_PERSISTENT;
7572 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007573 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007574 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007575 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
7576 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
7577 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08007578 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
7579 } else if (adj >= HOME_APP_ADJ) {
7580 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
7581 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007582 } else if (adj >= SECONDARY_SERVER_ADJ) {
7583 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007584 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackborn5383f502010-10-22 12:59:20 -07007585 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007586 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
7587 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007588 } else if (adj >= VISIBLE_APP_ADJ) {
7589 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
7590 } else {
7591 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
7592 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007593 currApp.importanceReasonCode = app.adjTypeCode;
7594 if (app.adjSource instanceof ProcessRecord) {
7595 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007596 } else if (app.adjSource instanceof ActivityRecord) {
7597 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007598 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
7599 }
7600 if (app.adjTarget instanceof ComponentName) {
7601 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
7602 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007603 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007604 // + " lru=" + currApp.lru);
7605 if (runList == null) {
7606 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
7607 }
7608 runList.add(currApp);
7609 }
7610 }
7611 }
7612 return runList;
7613 }
7614
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007615 public List<ApplicationInfo> getRunningExternalApplications() {
7616 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
7617 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
7618 if (runningApps != null && runningApps.size() > 0) {
7619 Set<String> extList = new HashSet<String>();
7620 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
7621 if (app.pkgList != null) {
7622 for (String pkg : app.pkgList) {
7623 extList.add(pkg);
7624 }
7625 }
7626 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007627 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007628 for (String pkg : extList) {
7629 try {
7630 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
7631 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
7632 retList.add(info);
7633 }
7634 } catch (RemoteException e) {
7635 }
7636 }
7637 }
7638 return retList;
7639 }
7640
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007641 @Override
7642 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007643 if (checkCallingPermission(android.Manifest.permission.DUMP)
7644 != PackageManager.PERMISSION_GRANTED) {
7645 pw.println("Permission Denial: can't dump ActivityManager from from pid="
7646 + Binder.getCallingPid()
7647 + ", uid=" + Binder.getCallingUid()
7648 + " without permission "
7649 + android.Manifest.permission.DUMP);
7650 return;
7651 }
7652
7653 boolean dumpAll = false;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007654 boolean dumpClient = false;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007655
7656 int opti = 0;
7657 while (opti < args.length) {
7658 String opt = args[opti];
7659 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
7660 break;
7661 }
7662 opti++;
7663 if ("-a".equals(opt)) {
7664 dumpAll = true;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007665 } else if ("-c".equals(opt)) {
7666 dumpClient = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007667 } else if ("-h".equals(opt)) {
7668 pw.println("Activity manager dump options:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007669 pw.println(" [-a] [-c] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007670 pw.println(" cmd may be one of:");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007671 pw.println(" a[ctivities]: activity stack state");
7672 pw.println(" b[roadcasts]: broadcast state");
7673 pw.println(" i[ntents]: pending intent state");
7674 pw.println(" p[rocesses]: process state");
7675 pw.println(" o[om]: out of memory management");
7676 pw.println(" prov[iders]: content provider state");
7677 pw.println(" s[ervices]: service state");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007678 pw.println(" service [COMP_SPEC]: service client-side state");
7679 pw.println(" cmd may also be a COMP_SPEC to dump activities.");
7680 pw.println(" COMP_SPEC may also be a component name (com.foo/.myApp),");
7681 pw.println(" a partial substring in a component name, an");
7682 pw.println(" ActivityRecord hex object identifier, or");
Dianne Hackbornf9302322011-06-14 18:36:14 -07007683 pw.println(" \"all\" for all objects, or");
7684 pw.println(" \"top\" for the top activity.");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007685 pw.println(" -a: include all available server state.");
7686 pw.println(" -c: include client state.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007687 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007688 } else {
7689 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007690 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007691 }
7692
7693 // Is the caller requesting to dump a particular piece of data?
7694 if (opti < args.length) {
7695 String cmd = args[opti];
7696 opti++;
7697 if ("activities".equals(cmd) || "a".equals(cmd)) {
7698 synchronized (this) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007699 dumpActivitiesLocked(fd, pw, args, opti, true, dumpClient);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007700 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007701 return;
7702 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
7703 synchronized (this) {
7704 dumpBroadcastsLocked(fd, pw, args, opti, true);
7705 }
7706 return;
7707 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
7708 synchronized (this) {
7709 dumpPendingIntentsLocked(fd, pw, args, opti, true);
7710 }
7711 return;
7712 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
7713 synchronized (this) {
7714 dumpProcessesLocked(fd, pw, args, opti, true);
7715 }
7716 return;
Dianne Hackborn287952c2010-09-22 22:34:31 -07007717 } else if ("oom".equals(cmd) || "o".equals(cmd)) {
7718 synchronized (this) {
7719 dumpOomLocked(fd, pw, args, opti, true);
7720 }
7721 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007722 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
7723 synchronized (this) {
7724 dumpProvidersLocked(fd, pw, args, opti, true);
7725 }
7726 return;
7727 } else if ("service".equals(cmd)) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007728 String[] newArgs;
7729 String name;
7730 if (opti >= args.length) {
7731 name = null;
7732 newArgs = EMPTY_STRING_ARRAY;
7733 } else {
7734 name = args[opti];
7735 opti++;
7736 newArgs = new String[args.length - opti];
7737 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
7738 }
7739 if (!dumpService(fd, pw, name, newArgs, 0, dumpAll)) {
7740 pw.println("No services match: " + name);
7741 pw.println("Use -h for help.");
7742 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007743 return;
7744 } else if ("services".equals(cmd) || "s".equals(cmd)) {
7745 synchronized (this) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007746 dumpServicesLocked(fd, pw, args, opti, true, dumpClient);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007747 }
7748 return;
Dianne Hackborn625ac272010-09-17 18:29:22 -07007749 } else {
7750 // Dumping a single activity?
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007751 if (!dumpActivity(fd, pw, cmd, args, opti, dumpAll)) {
7752 pw.println("Bad activity command, or no activities match: " + cmd);
7753 pw.println("Use -h for help.");
Dianne Hackborn625ac272010-09-17 18:29:22 -07007754 }
Dianne Hackborn30d71892010-12-11 10:37:55 -08007755 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007756 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007757 }
7758
7759 // No piece of data specified, dump everything.
7760 synchronized (this) {
7761 boolean needSep;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007762 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007763 if (needSep) {
7764 pw.println(" ");
7765 }
7766 if (dumpAll) {
7767 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007768 }
7769 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
7770 if (needSep) {
7771 pw.println(" ");
7772 }
7773 if (dumpAll) {
7774 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007775 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007776 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007777 if (needSep) {
7778 pw.println(" ");
7779 }
7780 if (dumpAll) {
7781 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007782 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007783 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll, dumpClient);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007784 if (needSep) {
7785 pw.println(" ");
7786 }
7787 if (dumpAll) {
7788 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007789 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007790 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, dumpClient);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007791 if (needSep) {
7792 pw.println(" ");
7793 }
7794 if (dumpAll) {
7795 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007796 }
7797 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
7798 }
7799 }
7800
7801 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007802 int opti, boolean dumpAll, boolean dumpClient) {
7803 pw.println("ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)");
7804 pw.println(" Main stack:");
7805 dumpHistoryList(fd, pw, mMainStack.mHistory, " ", "Hist", true, !dumpAll, dumpClient);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007806 pw.println(" ");
7807 pw.println(" Running activities (most recent first):");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007808 dumpHistoryList(fd, pw, mMainStack.mLRUActivities, " ", "Run", false, !dumpAll, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007809 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007810 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007811 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007812 dumpHistoryList(fd, pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false,
7813 !dumpAll, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007814 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007815 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007816 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007817 pw.println(" Activities waiting to stop:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007818 dumpHistoryList(fd, pw, mMainStack.mStoppingActivities, " ", "Stop", false,
7819 !dumpAll, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007820 }
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08007821 if (mMainStack.mGoingToSleepActivities.size() > 0) {
7822 pw.println(" ");
7823 pw.println(" Activities waiting to sleep:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007824 dumpHistoryList(fd, pw, mMainStack.mGoingToSleepActivities, " ", "Sleep", false,
7825 !dumpAll, false);
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08007826 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007827 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007828 pw.println(" ");
7829 pw.println(" Activities waiting to finish:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007830 dumpHistoryList(fd, pw, mMainStack.mFinishingActivities, " ", "Fin", false,
7831 !dumpAll, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007832 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007833
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007834 pw.println(" ");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007835 if (mMainStack.mPausingActivity != null) {
7836 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
7837 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007838 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007839 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007840 if (dumpAll) {
7841 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
7842 pw.println(" mSleepTimeout: " + mMainStack.mSleepTimeout);
7843 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007844
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007845 if (mRecentTasks.size() > 0) {
7846 pw.println();
7847 pw.println(" Recent tasks:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007848
7849 final int N = mRecentTasks.size();
7850 for (int i=0; i<N; i++) {
7851 TaskRecord tr = mRecentTasks.get(i);
7852 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
7853 pw.println(tr);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007854 if (dumpAll) {
7855 mRecentTasks.get(i).dump(pw, " ");
7856 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007857 }
7858 }
7859
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007860 if (dumpAll) {
7861 pw.println(" ");
7862 pw.println(" mCurTask: " + mCurTask);
7863 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007864
7865 return true;
7866 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07007867
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007868 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7869 int opti, boolean dumpAll) {
7870 boolean needSep = false;
7871 int numPers = 0;
7872
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007873 pw.println("ACTIVITY MANAGER RUNNING PROCESSES (dumpsys activity processes)");
7874
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007875 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007876 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
7877 final int NA = procs.size();
7878 for (int ia=0; ia<NA; ia++) {
7879 if (!needSep) {
7880 pw.println(" All known processes:");
7881 needSep = true;
7882 }
7883 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007884 pw.print(r.persistent ? " *PERS*" : " *APP*");
7885 pw.print(" UID "); pw.print(procs.keyAt(ia));
7886 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007887 r.dump(pw, " ");
7888 if (r.persistent) {
7889 numPers++;
7890 }
7891 }
7892 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007893 }
7894
7895 if (mLruProcesses.size() > 0) {
7896 if (needSep) pw.println(" ");
7897 needSep = true;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007898 pw.println(" Process LRU list (most recent first):");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007899 dumpProcessOomList(pw, this, mLruProcesses, " ",
7900 "Proc", "PERS", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007901 needSep = true;
7902 }
7903
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007904 if (dumpAll) {
7905 synchronized (mPidsSelfLocked) {
7906 if (mPidsSelfLocked.size() > 0) {
7907 if (needSep) pw.println(" ");
7908 needSep = true;
7909 pw.println(" PID mappings:");
7910 for (int i=0; i<mPidsSelfLocked.size(); i++) {
7911 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
7912 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
7913 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007914 }
7915 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007916 }
7917
7918 if (mForegroundProcesses.size() > 0) {
7919 if (needSep) pw.println(" ");
7920 needSep = true;
7921 pw.println(" Foreground Processes:");
7922 for (int i=0; i<mForegroundProcesses.size(); i++) {
7923 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
7924 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007925 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007926 }
7927
7928 if (mPersistentStartingProcesses.size() > 0) {
7929 if (needSep) pw.println(" ");
7930 needSep = true;
7931 pw.println(" Persisent processes that are starting:");
7932 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007933 "Starting Norm", "Restarting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007934 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007935
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007936 if (mRemovedProcesses.size() > 0) {
7937 if (needSep) pw.println(" ");
7938 needSep = true;
7939 pw.println(" Processes that are being removed:");
7940 dumpProcessList(pw, this, mRemovedProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007941 "Removed Norm", "Removed PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007942 }
7943
7944 if (mProcessesOnHold.size() > 0) {
7945 if (needSep) pw.println(" ");
7946 needSep = true;
7947 pw.println(" Processes that are on old until the system is ready:");
7948 dumpProcessList(pw, this, mProcessesOnHold, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007949 "OnHold Norm", "OnHold PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007950 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007951
Dianne Hackborn287952c2010-09-22 22:34:31 -07007952 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007953
7954 if (mProcessCrashTimes.getMap().size() > 0) {
7955 if (needSep) pw.println(" ");
7956 needSep = true;
7957 pw.println(" Time since processes crashed:");
7958 long now = SystemClock.uptimeMillis();
7959 for (Map.Entry<String, SparseArray<Long>> procs
7960 : mProcessCrashTimes.getMap().entrySet()) {
7961 SparseArray<Long> uids = procs.getValue();
7962 final int N = uids.size();
7963 for (int i=0; i<N; i++) {
7964 pw.print(" Process "); pw.print(procs.getKey());
7965 pw.print(" uid "); pw.print(uids.keyAt(i));
7966 pw.print(": last crashed ");
7967 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007968 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007969 }
7970 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007971 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007972
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007973 if (mBadProcesses.getMap().size() > 0) {
7974 if (needSep) pw.println(" ");
7975 needSep = true;
7976 pw.println(" Bad processes:");
7977 for (Map.Entry<String, SparseArray<Long>> procs
7978 : mBadProcesses.getMap().entrySet()) {
7979 SparseArray<Long> uids = procs.getValue();
7980 final int N = uids.size();
7981 for (int i=0; i<N; i++) {
7982 pw.print(" Bad process "); pw.print(procs.getKey());
7983 pw.print(" uid "); pw.print(uids.keyAt(i));
7984 pw.print(": crashed at time ");
7985 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007986 }
7987 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007988 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007989
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007990 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007991 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007992 if (mHeavyWeightProcess != null) {
7993 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7994 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007995 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007996 if (dumpAll) {
7997 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackborn3d0724d2011-05-12 15:39:41 -07007998 if (mCompatModePackages.getPackages().size() > 0) {
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07007999 pw.println(" mScreenCompatPackages:");
8000 for (Map.Entry<String, Integer> entry
8001 : mCompatModePackages.getPackages().entrySet()) {
8002 String pkg = entry.getKey();
8003 int mode = entry.getValue();
8004 pw.print(" "); pw.print(pkg); pw.print(": ");
8005 pw.print(mode); pw.println();
8006 }
Dianne Hackbornaa9d84c2011-05-09 19:00:59 -07008007 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008008 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008009 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
8010 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
8011 || mOrigWaitForDebugger) {
8012 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
8013 + " mDebugTransient=" + mDebugTransient
8014 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
8015 }
8016 if (mAlwaysFinishActivities || mController != null) {
8017 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
8018 + " mController=" + mController);
8019 }
8020 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008021 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008022 pw.println(" mStartRunning=" + mStartRunning
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07008023 + " mProcessesReady=" + mProcessesReady
8024 + " mSystemReady=" + mSystemReady);
8025 pw.println(" mBooting=" + mBooting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008026 + " mBooted=" + mBooted
8027 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008028 pw.print(" mLastPowerCheckRealtime=");
8029 TimeUtils.formatDuration(mLastPowerCheckRealtime, pw);
8030 pw.println("");
8031 pw.print(" mLastPowerCheckUptime=");
8032 TimeUtils.formatDuration(mLastPowerCheckUptime, pw);
8033 pw.println("");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008034 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
8035 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07008036 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008037 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008038
8039 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008040 }
8041
Dianne Hackborn287952c2010-09-22 22:34:31 -07008042 boolean dumpProcessesToGc(FileDescriptor fd, PrintWriter pw, String[] args,
8043 int opti, boolean needSep, boolean dumpAll) {
8044 if (mProcessesToGc.size() > 0) {
8045 if (needSep) pw.println(" ");
8046 needSep = true;
8047 pw.println(" Processes that are waiting to GC:");
8048 long now = SystemClock.uptimeMillis();
8049 for (int i=0; i<mProcessesToGc.size(); i++) {
8050 ProcessRecord proc = mProcessesToGc.get(i);
8051 pw.print(" Process "); pw.println(proc);
8052 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
8053 pw.print(", last gced=");
8054 pw.print(now-proc.lastRequestedGc);
8055 pw.print(" ms ago, last lowMem=");
8056 pw.print(now-proc.lastLowMemory);
8057 pw.println(" ms ago");
8058
8059 }
8060 }
8061 return needSep;
8062 }
8063
8064 boolean dumpOomLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8065 int opti, boolean dumpAll) {
8066 boolean needSep = false;
8067
8068 if (mLruProcesses.size() > 0) {
8069 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>(mLruProcesses);
8070
8071 Comparator<ProcessRecord> comparator = new Comparator<ProcessRecord>() {
8072 @Override
8073 public int compare(ProcessRecord object1, ProcessRecord object2) {
8074 if (object1.setAdj != object2.setAdj) {
8075 return object1.setAdj > object2.setAdj ? -1 : 1;
8076 }
8077 if (object1.setSchedGroup != object2.setSchedGroup) {
8078 return object1.setSchedGroup > object2.setSchedGroup ? -1 : 1;
8079 }
8080 if (object1.keeping != object2.keeping) {
8081 return object1.keeping ? -1 : 1;
8082 }
8083 if (object1.pid != object2.pid) {
8084 return object1.pid > object2.pid ? -1 : 1;
8085 }
8086 return 0;
8087 }
8088 };
8089
8090 Collections.sort(procs, comparator);
8091
8092 if (needSep) pw.println(" ");
8093 needSep = true;
8094 pw.println(" Process OOM control:");
8095 dumpProcessOomList(pw, this, procs, " ",
8096 "Proc", "PERS", true);
8097 needSep = true;
8098 }
8099
8100 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
8101
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008102 pw.println();
Dianne Hackborn287952c2010-09-22 22:34:31 -07008103 pw.println(" mHomeProcess: " + mHomeProcess);
8104 if (mHeavyWeightProcess != null) {
8105 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
8106 }
8107
8108 return true;
8109 }
8110
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008111 /**
8112 * There are three ways to call this:
8113 * - no service specified: dump all the services
8114 * - a flattened component name that matched an existing service was specified as the
8115 * first arg: dump that one service
8116 * - the first arg isn't the flattened component name of an existing service:
8117 * dump all services whose component contains the first arg as a substring
8118 */
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008119 protected boolean dumpService(FileDescriptor fd, PrintWriter pw, String name, String[] args,
8120 int opti, boolean dumpAll) {
8121 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008122
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008123 if ("all".equals(name)) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07008124 synchronized (this) {
8125 for (ServiceRecord r1 : mServices.values()) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008126 services.add(r1);
8127 }
8128 }
8129 } else {
8130 ComponentName componentName = name != null
8131 ? ComponentName.unflattenFromString(name) : null;
8132 int objectId = 0;
8133 if (componentName == null) {
8134 // Not a '/' separated full component name; maybe an object ID?
8135 try {
8136 objectId = Integer.parseInt(name, 16);
8137 name = null;
8138 componentName = null;
8139 } catch (RuntimeException e) {
8140 }
8141 }
8142
8143 synchronized (this) {
8144 for (ServiceRecord r1 : mServices.values()) {
8145 if (componentName != null) {
8146 if (r1.name.equals(componentName)) {
8147 services.add(r1);
8148 }
8149 } else if (name != null) {
8150 if (r1.name.flattenToString().contains(name)) {
8151 services.add(r1);
8152 }
8153 } else if (System.identityHashCode(r1) == objectId) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07008154 services.add(r1);
8155 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008156 }
8157 }
8158 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008159
8160 if (services.size() <= 0) {
8161 return false;
8162 }
8163
8164 boolean needSep = false;
8165 for (int i=0; i<services.size(); i++) {
8166 if (needSep) {
8167 pw.println();
8168 }
8169 needSep = true;
8170 dumpService("", fd, pw, services.get(i), args, dumpAll);
8171 }
8172 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008173 }
8174
8175 /**
8176 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
8177 * there is a thread associated with the service.
8178 */
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008179 private void dumpService(String prefix, FileDescriptor fd, PrintWriter pw,
8180 final ServiceRecord r, String[] args, boolean dumpAll) {
8181 String innerPrefix = prefix + " ";
8182 synchronized (this) {
8183 pw.print(prefix); pw.print("SERVICE ");
8184 pw.print(r.shortName); pw.print(" ");
8185 pw.print(Integer.toHexString(System.identityHashCode(r)));
8186 pw.print(" pid=");
8187 if (r.app != null) pw.println(r.app.pid);
8188 else pw.println("(not running)");
8189 if (dumpAll) {
8190 r.dump(pw, innerPrefix);
8191 }
8192 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008193 if (r.app != null && r.app.thread != null) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008194 pw.print(prefix); pw.println(" Client:");
8195 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008196 try {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008197 TransferPipe tp = new TransferPipe();
8198 try {
8199 r.app.thread.dumpService(tp.getWriteFd().getFileDescriptor(), r, args);
8200 tp.setBufferPrefix(prefix + " ");
8201 tp.go(fd);
8202 } finally {
8203 tp.kill();
8204 }
8205 } catch (IOException e) {
8206 pw.println(prefix + " Failure while dumping the service: " + e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008207 } catch (RemoteException e) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008208 pw.println(prefix + " Got a RemoteException while dumping the service");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008209 }
8210 }
8211 }
8212
Dianne Hackborn625ac272010-09-17 18:29:22 -07008213 /**
8214 * There are three things that cmd can be:
8215 * - a flattened component name that matched an existing activity
8216 * - the cmd arg isn't the flattened component name of an existing activity:
8217 * dump all activity whose component contains the cmd as a substring
8218 * - A hex number of the ActivityRecord object instance.
8219 */
8220 protected boolean dumpActivity(FileDescriptor fd, PrintWriter pw, String name, String[] args,
8221 int opti, boolean dumpAll) {
Dianne Hackborn625ac272010-09-17 18:29:22 -07008222 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008223
8224 if ("all".equals(name)) {
8225 synchronized (this) {
8226 for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
Dianne Hackborn625ac272010-09-17 18:29:22 -07008227 activities.add(r1);
8228 }
8229 }
Dianne Hackbornf9302322011-06-14 18:36:14 -07008230 } else if ("top".equals(name)) {
8231 synchronized (this) {
8232 final int N = mMainStack.mHistory.size();
8233 if (N > 0) {
8234 activities.add((ActivityRecord)mMainStack.mHistory.get(N-1));
8235 }
8236 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008237 } else {
8238 ComponentName componentName = ComponentName.unflattenFromString(name);
8239 int objectId = 0;
8240 if (componentName == null) {
8241 // Not a '/' separated full component name; maybe an object ID?
8242 try {
8243 objectId = Integer.parseInt(name, 16);
8244 name = null;
8245 componentName = null;
8246 } catch (RuntimeException e) {
8247 }
8248 }
8249
8250 synchronized (this) {
8251 for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
8252 if (componentName != null) {
8253 if (r1.intent.getComponent().equals(componentName)) {
8254 activities.add(r1);
8255 }
8256 } else if (name != null) {
8257 if (r1.intent.getComponent().flattenToString().contains(name)) {
8258 activities.add(r1);
8259 }
8260 } else if (System.identityHashCode(r1) == objectId) {
8261 activities.add(r1);
8262 }
8263 }
8264 }
Dianne Hackborn625ac272010-09-17 18:29:22 -07008265 }
8266
8267 if (activities.size() <= 0) {
8268 return false;
8269 }
8270
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008271 String[] newArgs = new String[args.length - opti];
8272 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
8273
Dianne Hackborn30d71892010-12-11 10:37:55 -08008274 TaskRecord lastTask = null;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008275 boolean needSep = false;
Dianne Hackborn30d71892010-12-11 10:37:55 -08008276 for (int i=activities.size()-1; i>=0; i--) {
8277 ActivityRecord r = (ActivityRecord)activities.get(i);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008278 if (needSep) {
8279 pw.println();
8280 }
8281 needSep = true;
8282 synchronized (this) {
8283 if (lastTask != r.task) {
8284 lastTask = r.task;
8285 pw.print("TASK "); pw.print(lastTask.affinity);
8286 pw.print(" id="); pw.println(lastTask.taskId);
8287 if (dumpAll) {
8288 lastTask.dump(pw, " ");
8289 }
Dianne Hackborn30d71892010-12-11 10:37:55 -08008290 }
8291 }
8292 dumpActivity(" ", fd, pw, activities.get(i), newArgs, dumpAll);
Dianne Hackborn625ac272010-09-17 18:29:22 -07008293 }
8294 return true;
8295 }
8296
8297 /**
8298 * Invokes IApplicationThread.dumpActivity() on the thread of the specified activity if
8299 * there is a thread associated with the activity.
8300 */
Dianne Hackborn30d71892010-12-11 10:37:55 -08008301 private void dumpActivity(String prefix, FileDescriptor fd, PrintWriter pw,
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008302 final ActivityRecord r, String[] args, boolean dumpAll) {
8303 String innerPrefix = prefix + " ";
Dianne Hackborn30d71892010-12-11 10:37:55 -08008304 synchronized (this) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008305 pw.print(prefix); pw.print("ACTIVITY "); pw.print(r.shortComponentName);
8306 pw.print(" "); pw.print(Integer.toHexString(System.identityHashCode(r)));
8307 pw.print(" pid=");
Dianne Hackborn30d71892010-12-11 10:37:55 -08008308 if (r.app != null) pw.println(r.app.pid);
8309 else pw.println("(not running)");
8310 if (dumpAll) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008311 r.dump(pw, innerPrefix);
Dianne Hackborn625ac272010-09-17 18:29:22 -07008312 }
Dianne Hackborn625ac272010-09-17 18:29:22 -07008313 }
8314 if (r.app != null && r.app.thread != null) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008315 // flush anything that is already in the PrintWriter since the thread is going
8316 // to write to the file descriptor directly
8317 pw.flush();
Dianne Hackborn625ac272010-09-17 18:29:22 -07008318 try {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008319 TransferPipe tp = new TransferPipe();
8320 try {
8321 r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(), r,
8322 innerPrefix, args);
8323 tp.go(fd);
8324 } finally {
8325 tp.kill();
8326 }
8327 } catch (IOException e) {
8328 pw.println(innerPrefix + "Failure while dumping the activity: " + e);
Dianne Hackborn625ac272010-09-17 18:29:22 -07008329 } catch (RemoteException e) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008330 pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
Dianne Hackborn625ac272010-09-17 18:29:22 -07008331 }
8332 }
8333 }
8334
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008335 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8336 int opti, boolean dumpAll) {
8337 boolean needSep = false;
8338
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008339 pw.println("ACTIVITY MANAGER BROADCAST STATE (dumpsys activity broadcasts)");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008340 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008341 if (mRegisteredReceivers.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008342 pw.println(" Registered Receivers:");
8343 Iterator it = mRegisteredReceivers.values().iterator();
8344 while (it.hasNext()) {
8345 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008346 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008347 r.dump(pw, " ");
8348 }
8349 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008350
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008351 pw.println();
8352 pw.println(" Receiver Resolver Table:");
8353 mReceiverResolver.dump(pw, null, " ", null, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008354 needSep = true;
8355 }
8356
8357 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
8358 || mPendingBroadcast != null) {
8359 if (mParallelBroadcasts.size() > 0) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008360 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008361 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008362 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008363 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
8364 pw.println(" Broadcast #" + i + ":");
8365 mParallelBroadcasts.get(i).dump(pw, " ");
8366 }
8367 if (mOrderedBroadcasts.size() > 0) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008368 pw.println();
Dianne Hackborn399cccb2010-04-13 22:57:49 -07008369 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008370 }
8371 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
8372 pw.println(" Serialized Broadcast #" + i + ":");
8373 mOrderedBroadcasts.get(i).dump(pw, " ");
8374 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008375 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008376 pw.println(" Pending broadcast:");
8377 if (mPendingBroadcast != null) {
8378 mPendingBroadcast.dump(pw, " ");
8379 } else {
8380 pw.println(" (null)");
8381 }
8382 needSep = true;
8383 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008384
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008385 if (needSep) {
8386 pw.println();
8387 }
8388 pw.println(" Historical broadcasts:");
8389 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
8390 BroadcastRecord r = mBroadcastHistory[i];
8391 if (r == null) {
8392 break;
8393 }
8394 if (dumpAll) {
8395 pw.print(" Historical Broadcast #"); pw.print(i); pw.println(":");
8396 r.dump(pw, " ");
8397 } else {
8398 if (i >= 50) {
8399 pw.println(" ...");
Dianne Hackborn12527f92009-11-11 17:39:50 -08008400 break;
8401 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008402 pw.print(" #"); pw.print(i); pw.print(": "); pw.println(r);
Dianne Hackborn12527f92009-11-11 17:39:50 -08008403 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008404 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008405 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008406
8407 if (mStickyBroadcasts != null) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008408 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008409 pw.println(" Sticky broadcasts:");
8410 StringBuilder sb = new StringBuilder(128);
8411 for (Map.Entry<String, ArrayList<Intent>> ent
8412 : mStickyBroadcasts.entrySet()) {
8413 pw.print(" * Sticky action "); pw.print(ent.getKey());
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008414 if (dumpAll) {
8415 pw.println(":");
8416 ArrayList<Intent> intents = ent.getValue();
8417 final int N = intents.size();
8418 for (int i=0; i<N; i++) {
8419 sb.setLength(0);
8420 sb.append(" Intent: ");
8421 intents.get(i).toShortString(sb, true, false);
8422 pw.println(sb.toString());
8423 Bundle bundle = intents.get(i).getExtras();
8424 if (bundle != null) {
8425 pw.print(" ");
8426 pw.println(bundle.toString());
8427 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008428 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008429 } else {
8430 pw.println("");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008431 }
8432 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008433 needSep = true;
8434 }
8435
8436 if (dumpAll) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008437 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008438 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008439 pw.println(" mHandler:");
8440 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008441 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008442 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008443
8444 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008445 }
8446
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008447 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008448 int opti, boolean dumpAll, boolean dumpClient) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008449 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008450
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008451 pw.println("ACTIVITY MANAGER SERVICES (dumpsys activity services)");
8452 if (mServices.size() > 0) {
8453 pw.println(" Active services:");
8454 long nowReal = SystemClock.elapsedRealtime();
8455 Iterator<ServiceRecord> it = mServices.values().iterator();
8456 needSep = false;
8457 while (it.hasNext()) {
8458 ServiceRecord r = it.next();
8459 if (needSep) {
8460 pw.println();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008461 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008462 pw.print(" * "); pw.println(r);
8463 if (dumpAll) {
8464 r.dump(pw, " ");
8465 needSep = true;
8466 } else {
8467 pw.print(" app="); pw.println(r.app);
8468 pw.print(" created=");
8469 TimeUtils.formatDuration(r.createTime, nowReal, pw);
8470 pw.print(" started="); pw.print(r.startRequested);
8471 pw.print(" connections="); pw.println(r.connections.size());
8472 }
8473 if (dumpClient && r.app != null && r.app.thread != null) {
8474 pw.println(" Client:");
8475 pw.flush();
8476 try {
8477 TransferPipe tp = new TransferPipe();
8478 try {
8479 r.app.thread.dumpService(
8480 tp.getWriteFd().getFileDescriptor(), r, args);
8481 tp.setBufferPrefix(" ");
8482 // Short timeout, since blocking here can
8483 // deadlock with the application.
8484 tp.go(fd, 2000);
8485 } finally {
8486 tp.kill();
8487 }
8488 } catch (IOException e) {
8489 pw.println(" Failure while dumping the service: " + e);
8490 } catch (RemoteException e) {
8491 pw.println(" Got a RemoteException while dumping the service");
8492 }
8493 needSep = true;
8494 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008495 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008496 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008497 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008498
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008499 if (mPendingServices.size() > 0) {
8500 if (needSep) pw.println(" ");
8501 pw.println(" Pending services:");
8502 for (int i=0; i<mPendingServices.size(); i++) {
8503 ServiceRecord r = mPendingServices.get(i);
8504 pw.print(" * Pending "); pw.println(r);
8505 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008506 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008507 needSep = true;
8508 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008509
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008510 if (mRestartingServices.size() > 0) {
8511 if (needSep) pw.println(" ");
8512 pw.println(" Restarting services:");
8513 for (int i=0; i<mRestartingServices.size(); i++) {
8514 ServiceRecord r = mRestartingServices.get(i);
8515 pw.print(" * Restarting "); pw.println(r);
8516 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008517 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008518 needSep = true;
8519 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008520
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008521 if (mStoppingServices.size() > 0) {
8522 if (needSep) pw.println(" ");
8523 pw.println(" Stopping services:");
8524 for (int i=0; i<mStoppingServices.size(); i++) {
8525 ServiceRecord r = mStoppingServices.get(i);
8526 pw.print(" * Stopping "); pw.println(r);
8527 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008528 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008529 needSep = true;
8530 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008531
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008532 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008533 if (mServiceConnections.size() > 0) {
8534 if (needSep) pw.println(" ");
8535 pw.println(" Connection bindings to services:");
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008536 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008537 = mServiceConnections.values().iterator();
8538 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008539 ArrayList<ConnectionRecord> r = it.next();
8540 for (int i=0; i<r.size(); i++) {
8541 pw.print(" * "); pw.println(r.get(i));
8542 r.get(i).dump(pw, " ");
8543 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008544 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008545 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008546 }
8547 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008548
8549 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008550 }
8551
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008552 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8553 int opti, boolean dumpAll) {
8554 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008555
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008556 pw.println("ACTIVITY MANAGER CONTENT PROVIDERS (dumpsys activity providers)");
8557 if (mProvidersByClass.size() > 0) {
8558 if (needSep) pw.println(" ");
8559 pw.println(" Published content providers (by class):");
8560 Iterator<Map.Entry<String, ContentProviderRecord>> it
8561 = mProvidersByClass.entrySet().iterator();
8562 while (it.hasNext()) {
8563 Map.Entry<String, ContentProviderRecord> e = it.next();
8564 ContentProviderRecord r = e.getValue();
8565 if (dumpAll) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008566 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008567 r.dump(pw, " ");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008568 } else {
8569 pw.print(" * "); pw.print(r.name.toShortString());
8570 if (r.app != null) {
8571 pw.println(":");
8572 pw.print(" "); pw.println(r.app);
8573 } else {
8574 pw.println();
8575 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008576 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008577 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008578 needSep = true;
8579 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008580
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008581 if (dumpAll) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008582 if (mProvidersByName.size() > 0) {
8583 pw.println(" ");
8584 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -07008585 Iterator<Map.Entry<String, ContentProviderRecord>> it
8586 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008587 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008588 Map.Entry<String, ContentProviderRecord> e = it.next();
8589 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008590 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
8591 pw.println(r);
8592 }
8593 needSep = true;
8594 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008595 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008596
8597 if (mLaunchingProviders.size() > 0) {
8598 if (needSep) pw.println(" ");
8599 pw.println(" Launching content providers:");
8600 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
8601 pw.print(" Launching #"); pw.print(i); pw.print(": ");
8602 pw.println(mLaunchingProviders.get(i));
8603 }
8604 needSep = true;
8605 }
8606
8607 if (mGrantedUriPermissions.size() > 0) {
8608 pw.println();
8609 pw.println("Granted Uri Permissions:");
8610 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
8611 int uid = mGrantedUriPermissions.keyAt(i);
8612 HashMap<Uri, UriPermission> perms
8613 = mGrantedUriPermissions.valueAt(i);
8614 pw.print(" * UID "); pw.print(uid);
8615 pw.println(" holds:");
8616 for (UriPermission perm : perms.values()) {
8617 pw.print(" "); pw.println(perm);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008618 if (dumpAll) {
8619 perm.dump(pw, " ");
8620 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008621 }
8622 }
8623 needSep = true;
8624 }
8625
8626 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008627 }
8628
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008629 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8630 int opti, boolean dumpAll) {
8631 boolean needSep = false;
8632
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008633 if (this.mIntentSenderRecords.size() > 0) {
8634 pw.println("ACTIVITY MANAGER PENDING INTENTS (dumpsys activity intents)");
8635 Iterator<WeakReference<PendingIntentRecord>> it
8636 = mIntentSenderRecords.values().iterator();
8637 while (it.hasNext()) {
8638 WeakReference<PendingIntentRecord> ref = it.next();
8639 PendingIntentRecord rec = ref != null ? ref.get(): null;
8640 needSep = true;
8641 if (rec != null) {
8642 pw.print(" * "); pw.println(rec);
8643 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008644 rec.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008645 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008646 } else {
8647 pw.print(" * "); pw.println(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008648 }
8649 }
8650 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008651
8652 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008653 }
8654
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008655 private static final void dumpHistoryList(FileDescriptor fd, PrintWriter pw, List list,
8656 String prefix, String label, boolean complete, boolean brief, boolean client) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008657 TaskRecord lastTask = null;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008658 boolean needNL = false;
8659 final String innerPrefix = prefix + " ";
8660 final String[] args = new String[0];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008661 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008662 final ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackbornf26fd992011-04-08 18:14:09 -07008663 final boolean full = !brief && (complete || !r.isInHistory());
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008664 if (needNL) {
8665 pw.println(" ");
8666 needNL = false;
8667 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008668 if (lastTask != r.task) {
8669 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008670 pw.print(prefix);
8671 pw.print(full ? "* " : " ");
8672 pw.println(lastTask);
8673 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008674 lastTask.dump(pw, prefix + " ");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008675 } else if (complete) {
8676 // Complete + brief == give a summary. Isn't that obvious?!?
8677 if (lastTask.intent != null) {
8678 pw.print(prefix); pw.print(" "); pw.println(lastTask.intent);
8679 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008680 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008681 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008682 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
8683 pw.print(" #"); pw.print(i); pw.print(": ");
8684 pw.println(r);
8685 if (full) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008686 r.dump(pw, innerPrefix);
8687 } else if (complete) {
8688 // Complete + brief == give a summary. Isn't that obvious?!?
8689 pw.print(innerPrefix); pw.println(r.intent);
8690 if (r.app != null) {
8691 pw.print(innerPrefix); pw.println(r.app);
8692 }
8693 }
8694 if (client && r.app != null && r.app.thread != null) {
8695 // flush anything that is already in the PrintWriter since the thread is going
8696 // to write to the file descriptor directly
8697 pw.flush();
8698 try {
8699 TransferPipe tp = new TransferPipe();
8700 try {
8701 r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(), r,
8702 innerPrefix, args);
8703 // Short timeout, since blocking here can
8704 // deadlock with the application.
8705 tp.go(fd, 2000);
8706 } finally {
8707 tp.kill();
8708 }
8709 } catch (IOException e) {
8710 pw.println(innerPrefix + "Failure while dumping the activity: " + e);
8711 } catch (RemoteException e) {
8712 pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
8713 }
8714 needNL = true;
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008715 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008716 }
8717 }
8718
Dianne Hackborn09c916b2009-12-08 14:50:51 -08008719 private static String buildOomTag(String prefix, String space, int val, int base) {
8720 if (val == base) {
8721 if (space == null) return prefix;
8722 return prefix + " ";
8723 }
8724 return prefix + "+" + Integer.toString(val-base);
8725 }
8726
8727 private static final int dumpProcessList(PrintWriter pw,
8728 ActivityManagerService service, List list,
Dianne Hackborn287952c2010-09-22 22:34:31 -07008729 String prefix, String normalLabel, String persistentLabel) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008730 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07008731 final int N = list.size()-1;
8732 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008733 ProcessRecord r = (ProcessRecord)list.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008734 pw.println(String.format("%s%s #%2d: %s",
8735 prefix, (r.persistent ? persistentLabel : normalLabel),
8736 i, r.toString()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008737 if (r.persistent) {
8738 numPers++;
8739 }
8740 }
8741 return numPers;
8742 }
8743
Dianne Hackborn287952c2010-09-22 22:34:31 -07008744 private static final void dumpProcessOomList(PrintWriter pw,
8745 ActivityManagerService service, List<ProcessRecord> list,
8746 String prefix, String normalLabel, String persistentLabel,
8747 boolean inclDetails) {
8748
8749 final long curRealtime = SystemClock.elapsedRealtime();
8750 final long realtimeSince = curRealtime - service.mLastPowerCheckRealtime;
8751 final long curUptime = SystemClock.uptimeMillis();
8752 final long uptimeSince = curUptime - service.mLastPowerCheckUptime;
8753
8754 final int N = list.size()-1;
8755 for (int i=N; i>=0; i--) {
8756 ProcessRecord r = list.get(i);
8757 String oomAdj;
8758 if (r.setAdj >= EMPTY_APP_ADJ) {
8759 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
8760 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
8761 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
8762 } else if (r.setAdj >= HOME_APP_ADJ) {
8763 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
8764 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
8765 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
8766 } else if (r.setAdj >= BACKUP_APP_ADJ) {
8767 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
8768 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
8769 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
8770 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
8771 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
8772 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
8773 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
8774 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
8775 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
8776 } else if (r.setAdj >= CORE_SERVER_ADJ) {
8777 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
8778 } else if (r.setAdj >= SYSTEM_ADJ) {
8779 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
8780 } else {
8781 oomAdj = Integer.toString(r.setAdj);
8782 }
8783 String schedGroup;
8784 switch (r.setSchedGroup) {
8785 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
8786 schedGroup = "B";
8787 break;
8788 case Process.THREAD_GROUP_DEFAULT:
8789 schedGroup = "F";
8790 break;
8791 default:
8792 schedGroup = Integer.toString(r.setSchedGroup);
8793 break;
8794 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07008795 String foreground;
8796 if (r.foregroundActivities) {
8797 foreground = "A";
8798 } else if (r.foregroundServices) {
8799 foreground = "S";
8800 } else {
8801 foreground = " ";
8802 }
8803 pw.println(String.format("%s%s #%2d: adj=%s/%s%s %s (%s)",
Dianne Hackborn287952c2010-09-22 22:34:31 -07008804 prefix, (r.persistent ? persistentLabel : normalLabel),
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07008805 N-i, oomAdj, schedGroup, foreground, r.toShortString(), r.adjType));
Dianne Hackborn287952c2010-09-22 22:34:31 -07008806 if (r.adjSource != null || r.adjTarget != null) {
8807 pw.print(prefix);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008808 pw.print(" ");
Dianne Hackborn287952c2010-09-22 22:34:31 -07008809 if (r.adjTarget instanceof ComponentName) {
8810 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
8811 } else if (r.adjTarget != null) {
8812 pw.print(r.adjTarget.toString());
8813 } else {
8814 pw.print("{null}");
8815 }
8816 pw.print("<=");
8817 if (r.adjSource instanceof ProcessRecord) {
8818 pw.print("Proc{");
8819 pw.print(((ProcessRecord)r.adjSource).toShortString());
8820 pw.println("}");
8821 } else if (r.adjSource != null) {
8822 pw.println(r.adjSource.toString());
8823 } else {
8824 pw.println("{null}");
8825 }
8826 }
8827 if (inclDetails) {
8828 pw.print(prefix);
8829 pw.print(" ");
8830 pw.print("oom: max="); pw.print(r.maxAdj);
8831 pw.print(" hidden="); pw.print(r.hiddenAdj);
8832 pw.print(" curRaw="); pw.print(r.curRawAdj);
8833 pw.print(" setRaw="); pw.print(r.setRawAdj);
8834 pw.print(" cur="); pw.print(r.curAdj);
8835 pw.print(" set="); pw.println(r.setAdj);
8836 pw.print(prefix);
8837 pw.print(" ");
8838 pw.print("keeping="); pw.print(r.keeping);
8839 pw.print(" hidden="); pw.print(r.hidden);
8840 pw.print(" empty="); pw.println(r.empty);
8841
8842 if (!r.keeping) {
8843 if (r.lastWakeTime != 0) {
8844 long wtime;
8845 BatteryStatsImpl stats = service.mBatteryStatsService.getActiveStatistics();
8846 synchronized (stats) {
8847 wtime = stats.getProcessWakeTime(r.info.uid,
8848 r.pid, curRealtime);
8849 }
8850 long timeUsed = wtime - r.lastWakeTime;
8851 pw.print(prefix);
8852 pw.print(" ");
8853 pw.print("keep awake over ");
8854 TimeUtils.formatDuration(realtimeSince, pw);
8855 pw.print(" used ");
8856 TimeUtils.formatDuration(timeUsed, pw);
8857 pw.print(" (");
8858 pw.print((timeUsed*100)/realtimeSince);
8859 pw.println("%)");
8860 }
8861 if (r.lastCpuTime != 0) {
8862 long timeUsed = r.curCpuTime - r.lastCpuTime;
8863 pw.print(prefix);
8864 pw.print(" ");
8865 pw.print("run cpu over ");
8866 TimeUtils.formatDuration(uptimeSince, pw);
8867 pw.print(" used ");
8868 TimeUtils.formatDuration(timeUsed, pw);
8869 pw.print(" (");
8870 pw.print((timeUsed*100)/uptimeSince);
8871 pw.println("%)");
8872 }
8873 }
8874 }
8875 }
8876 }
8877
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008878 ArrayList<ProcessRecord> collectProcesses(PrintWriter pw, String[] args) {
8879 ArrayList<ProcessRecord> procs;
8880 synchronized (this) {
8881 if (args != null && args.length > 0
8882 && args[0].charAt(0) != '-') {
8883 procs = new ArrayList<ProcessRecord>();
8884 int pid = -1;
8885 try {
8886 pid = Integer.parseInt(args[0]);
8887 } catch (NumberFormatException e) {
8888
8889 }
8890 for (int i=mLruProcesses.size()-1; i>=0; i--) {
8891 ProcessRecord proc = mLruProcesses.get(i);
8892 if (proc.pid == pid) {
8893 procs.add(proc);
8894 } else if (proc.processName.equals(args[0])) {
8895 procs.add(proc);
8896 }
8897 }
8898 if (procs.size() <= 0) {
8899 pw.println("No process found for: " + args[0]);
8900 return null;
8901 }
8902 } else {
8903 procs = new ArrayList<ProcessRecord>(mLruProcesses);
8904 }
8905 }
8906 return procs;
8907 }
8908
8909 final void dumpGraphicsHardwareUsage(FileDescriptor fd,
8910 PrintWriter pw, String[] args) {
8911 ArrayList<ProcessRecord> procs = collectProcesses(pw, args);
8912 if (procs == null) {
8913 return;
8914 }
8915
8916 long uptime = SystemClock.uptimeMillis();
8917 long realtime = SystemClock.elapsedRealtime();
8918 pw.println("Applications Graphics Acceleration Info:");
8919 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
8920
8921 String callArgs[] = {"graphics"};
8922 for (int i = procs.size() - 1 ; i >= 0 ; i--) {
8923 ProcessRecord r = procs.get(i);
Chet Haase9c1e23b2011-03-24 10:51:31 -07008924 if (r.thread != null) {
8925 pw.println("\n** Graphics info for pid " + r.pid + " [" + r.processName + "] **");
8926 pw.flush();
8927 try {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008928 TransferPipe.goDump(r.thread.asBinder(), fd, callArgs);
8929 } catch (IOException e) {
8930 pw.println("Failure: " + e);
8931 pw.flush();
Chet Haase9c1e23b2011-03-24 10:51:31 -07008932 } catch (RemoteException e) {
8933 pw.println("Got RemoteException!");
8934 pw.flush();
8935 }
8936 }
8937 }
Chet Haase9c1e23b2011-03-24 10:51:31 -07008938 }
8939
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008940 final void dumpApplicationMemoryUsage(FileDescriptor fd,
8941 PrintWriter pw, String prefix, String[] args) {
8942 ArrayList<ProcessRecord> procs = collectProcesses(pw, args);
8943 if (procs == null) {
8944 return;
8945 }
8946
Dianne Hackborn6447ca32009-04-07 19:50:08 -07008947 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008948 long uptime = SystemClock.uptimeMillis();
8949 long realtime = SystemClock.elapsedRealtime();
8950
8951 if (isCheckinRequest) {
8952 // short checkin version
8953 pw.println(uptime + "," + realtime);
8954 pw.flush();
8955 } else {
8956 pw.println("Applications Memory Usage (kB):");
8957 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
8958 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008959 for (int i = procs.size() - 1 ; i >= 0 ; i--) {
8960 ProcessRecord r = procs.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008961 if (r.thread != null) {
8962 if (!isCheckinRequest) {
8963 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
8964 pw.flush();
8965 }
8966 try {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008967 TransferPipe.goDump(r.thread.asBinder(), fd, args);
8968 } catch (IOException e) {
8969 pw.println("Failure: " + e);
8970 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008971 } catch (RemoteException e) {
8972 if (!isCheckinRequest) {
8973 pw.println("Got RemoteException!");
8974 pw.flush();
8975 }
8976 }
8977 }
8978 }
8979 }
8980
8981 /**
8982 * Searches array of arguments for the specified string
8983 * @param args array of argument strings
8984 * @param value value to search for
8985 * @return true if the value is contained in the array
8986 */
8987 private static boolean scanArgs(String[] args, String value) {
8988 if (args != null) {
8989 for (String arg : args) {
8990 if (value.equals(arg)) {
8991 return true;
8992 }
8993 }
8994 }
8995 return false;
8996 }
8997
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008998 private final void killServicesLocked(ProcessRecord app,
8999 boolean allowRestart) {
9000 // Report disconnected services.
9001 if (false) {
9002 // XXX we are letting the client link to the service for
9003 // death notifications.
9004 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009005 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009006 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009007 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009008 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009009 Iterator<ArrayList<ConnectionRecord>> jt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009010 = r.connections.values().iterator();
9011 while (jt.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009012 ArrayList<ConnectionRecord> cl = jt.next();
9013 for (int i=0; i<cl.size(); i++) {
9014 ConnectionRecord c = cl.get(i);
9015 if (c.binding.client != app) {
9016 try {
9017 //c.conn.connected(r.className, null);
9018 } catch (Exception e) {
9019 // todo: this should be asynchronous!
9020 Slog.w(TAG, "Exception thrown disconnected servce "
9021 + r.shortName
9022 + " from app " + app.processName, e);
9023 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009024 }
9025 }
9026 }
9027 }
9028 }
9029 }
9030 }
9031
9032 // Clean up any connections this application has to other services.
9033 if (app.connections.size() > 0) {
9034 Iterator<ConnectionRecord> it = app.connections.iterator();
9035 while (it.hasNext()) {
9036 ConnectionRecord r = it.next();
9037 removeConnectionLocked(r, app, null);
9038 }
9039 }
9040 app.connections.clear();
9041
9042 if (app.services.size() != 0) {
9043 // Any services running in the application need to be placed
9044 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07009045 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009046 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009047 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009048 synchronized (sr.stats.getBatteryStats()) {
9049 sr.stats.stopLaunchedLocked();
9050 }
9051 sr.app = null;
9052 sr.executeNesting = 0;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009053 if (mStoppingServices.remove(sr)) {
9054 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
9055 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009056
9057 boolean hasClients = sr.bindings.size() > 0;
9058 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009059 Iterator<IntentBindRecord> bindings
9060 = sr.bindings.values().iterator();
9061 while (bindings.hasNext()) {
9062 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009063 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009064 + ": shouldUnbind=" + b.hasBound);
9065 b.binder = null;
9066 b.requested = b.received = b.hasBound = false;
9067 }
9068 }
9069
Dianne Hackborn070783f2010-12-29 16:46:28 -08009070 if (sr.crashCount >= 2 && (sr.serviceInfo.applicationInfo.flags
9071 &ApplicationInfo.FLAG_PERSISTENT) == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009072 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009073 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009074 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009075 sr.crashCount, sr.shortName, app.pid);
9076 bringDownServiceLocked(sr, true);
9077 } else if (!allowRestart) {
9078 bringDownServiceLocked(sr, true);
9079 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009080 boolean canceled = scheduleServiceRestartLocked(sr, true);
9081
9082 // Should the service remain running? Note that in the
9083 // extreme case of so many attempts to deliver a command
9084 // that it failed, that we also will stop it here.
9085 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
9086 if (sr.pendingStarts.size() == 0) {
9087 sr.startRequested = false;
9088 if (!hasClients) {
9089 // Whoops, no reason to restart!
9090 bringDownServiceLocked(sr, true);
9091 }
9092 }
9093 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009094 }
9095 }
9096
9097 if (!allowRestart) {
9098 app.services.clear();
9099 }
9100 }
9101
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009102 // Make sure we have no more records on the stopping list.
9103 int i = mStoppingServices.size();
9104 while (i > 0) {
9105 i--;
9106 ServiceRecord sr = mStoppingServices.get(i);
9107 if (sr.app == app) {
9108 mStoppingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009109 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009110 }
9111 }
9112
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009113 app.executingServices.clear();
9114 }
9115
9116 private final void removeDyingProviderLocked(ProcessRecord proc,
9117 ContentProviderRecord cpr) {
9118 synchronized (cpr) {
9119 cpr.launchingApp = null;
9120 cpr.notifyAll();
9121 }
9122
9123 mProvidersByClass.remove(cpr.info.name);
9124 String names[] = cpr.info.authority.split(";");
9125 for (int j = 0; j < names.length; j++) {
9126 mProvidersByName.remove(names[j]);
9127 }
9128
9129 Iterator<ProcessRecord> cit = cpr.clients.iterator();
9130 while (cit.hasNext()) {
9131 ProcessRecord capp = cit.next();
9132 if (!capp.persistent && capp.thread != null
9133 && capp.pid != 0
9134 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07009135 Slog.i(TAG, "Kill " + capp.processName
9136 + " (pid " + capp.pid + "): provider " + cpr.info.name
9137 + " in dying process " + proc.processName);
9138 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
9139 capp.processName, capp.setAdj, "dying provider " + proc.processName);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07009140 Process.killProcessQuiet(capp.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009141 }
9142 }
9143
9144 mLaunchingProviders.remove(cpr);
9145 }
9146
9147 /**
9148 * Main code for cleaning up a process when it has gone away. This is
9149 * called both as a result of the process dying, or directly when stopping
9150 * a process when running in single process mode.
9151 */
9152 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
9153 boolean restarting, int index) {
9154 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009155 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009156 }
9157
Dianne Hackborn36124872009-10-08 16:22:03 -07009158 mProcessesToGc.remove(app);
9159
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009160 // Dismiss any open dialogs.
9161 if (app.crashDialog != null) {
9162 app.crashDialog.dismiss();
9163 app.crashDialog = null;
9164 }
9165 if (app.anrDialog != null) {
9166 app.anrDialog.dismiss();
9167 app.anrDialog = null;
9168 }
9169 if (app.waitDialog != null) {
9170 app.waitDialog.dismiss();
9171 app.waitDialog = null;
9172 }
9173
9174 app.crashing = false;
9175 app.notResponding = false;
9176
9177 app.resetPackageList();
9178 app.thread = null;
9179 app.forcingToForeground = null;
9180 app.foregroundServices = false;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07009181 app.foregroundActivities = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009182
9183 killServicesLocked(app, true);
9184
9185 boolean restart = false;
9186
9187 int NL = mLaunchingProviders.size();
9188
9189 // Remove published content providers.
9190 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009191 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009192 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009193 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009194 cpr.provider = null;
9195 cpr.app = null;
9196
9197 // See if someone is waiting for this provider... in which
9198 // case we don't remove it, but just let it restart.
9199 int i = 0;
9200 if (!app.bad) {
9201 for (; i<NL; i++) {
9202 if (mLaunchingProviders.get(i) == cpr) {
9203 restart = true;
9204 break;
9205 }
9206 }
9207 } else {
9208 i = NL;
9209 }
9210
9211 if (i >= NL) {
9212 removeDyingProviderLocked(app, cpr);
9213 NL = mLaunchingProviders.size();
9214 }
9215 }
9216 app.pubProviders.clear();
9217 }
9218
Dianne Hackbornf670ef72009-11-16 13:59:16 -08009219 // Take care of any launching providers waiting for this process.
9220 if (checkAppInLaunchingProvidersLocked(app, false)) {
9221 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009222 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08009223
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009224 // Unregister from connected content providers.
9225 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07009226 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009227 while (it.hasNext()) {
9228 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
9229 cpr.clients.remove(app);
9230 }
9231 app.conProviders.clear();
9232 }
9233
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009234 // At this point there may be remaining entries in mLaunchingProviders
9235 // where we were the only one waiting, so they are no longer of use.
9236 // Look for these and clean up if found.
9237 // XXX Commented out for now. Trying to figure out a way to reproduce
9238 // the actual situation to identify what is actually going on.
9239 if (false) {
9240 for (int i=0; i<NL; i++) {
9241 ContentProviderRecord cpr = (ContentProviderRecord)
9242 mLaunchingProviders.get(i);
9243 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
9244 synchronized (cpr) {
9245 cpr.launchingApp = null;
9246 cpr.notifyAll();
9247 }
9248 }
9249 }
9250 }
9251
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009252 skipCurrentReceiverLocked(app);
9253
9254 // Unregister any receivers.
9255 if (app.receivers.size() > 0) {
9256 Iterator<ReceiverList> it = app.receivers.iterator();
9257 while (it.hasNext()) {
9258 removeReceiverLocked(it.next());
9259 }
9260 app.receivers.clear();
9261 }
9262
Christopher Tate181fafa2009-05-14 11:12:14 -07009263 // If the app is undergoing backup, tell the backup manager about it
9264 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009265 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -07009266 try {
9267 IBackupManager bm = IBackupManager.Stub.asInterface(
9268 ServiceManager.getService(Context.BACKUP_SERVICE));
9269 bm.agentDisconnected(app.info.packageName);
9270 } catch (RemoteException e) {
9271 // can't happen; backup manager is local
9272 }
9273 }
9274
Jeff Sharkey287bd832011-05-28 19:36:26 -07009275 mHandler.obtainMessage(DISPATCH_PROCESS_DIED, app.pid, app.info.uid, null).sendToTarget();
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07009276
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009277 // If the caller is restarting this app, then leave it in its
9278 // current lists and let the caller take care of it.
9279 if (restarting) {
9280 return;
9281 }
9282
9283 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009284 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009285 "Removing non-persistent process during cleanup: " + app);
9286 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07009287 if (mHeavyWeightProcess == app) {
9288 mHeavyWeightProcess = null;
9289 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
9290 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009291 } else if (!app.removed) {
9292 // This app is persistent, so we need to keep its record around.
9293 // If it is not already on the pending app list, add it there
9294 // and start a new process for it.
9295 app.thread = null;
9296 app.forcingToForeground = null;
9297 app.foregroundServices = false;
9298 if (mPersistentStartingProcesses.indexOf(app) < 0) {
9299 mPersistentStartingProcesses.add(app);
9300 restart = true;
9301 }
9302 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07009303 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
9304 "Clean-up removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009305 mProcessesOnHold.remove(app);
9306
The Android Open Source Project4df24232009-03-05 14:34:35 -08009307 if (app == mHomeProcess) {
9308 mHomeProcess = null;
9309 }
9310
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009311 if (restart) {
9312 // We have components that still need to be running in the
9313 // process, so re-launch it.
9314 mProcessNames.put(app.processName, app.info.uid, app);
9315 startProcessLocked(app, "restart", app.processName);
9316 } else if (app.pid > 0 && app.pid != MY_PID) {
9317 // Goodbye!
9318 synchronized (mPidsSelfLocked) {
9319 mPidsSelfLocked.remove(app.pid);
9320 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
9321 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009322 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009323 }
9324 }
9325
Dianne Hackbornf670ef72009-11-16 13:59:16 -08009326 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
9327 // Look through the content providers we are waiting to have launched,
9328 // and if any run in this process then either schedule a restart of
9329 // the process or kill the client waiting for it if this process has
9330 // gone bad.
9331 int NL = mLaunchingProviders.size();
9332 boolean restart = false;
9333 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009334 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08009335 if (cpr.launchingApp == app) {
9336 if (!alwaysBad && !app.bad) {
9337 restart = true;
9338 } else {
9339 removeDyingProviderLocked(app, cpr);
9340 NL = mLaunchingProviders.size();
9341 }
9342 }
9343 }
9344 return restart;
9345 }
9346
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009347 // =========================================================
9348 // SERVICES
9349 // =========================================================
9350
9351 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
9352 ActivityManager.RunningServiceInfo info =
9353 new ActivityManager.RunningServiceInfo();
9354 info.service = r.name;
9355 if (r.app != null) {
9356 info.pid = r.app.pid;
9357 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -07009358 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009359 info.process = r.processName;
9360 info.foreground = r.isForeground;
9361 info.activeSince = r.createTime;
9362 info.started = r.startRequested;
9363 info.clientCount = r.connections.size();
9364 info.crashCount = r.crashCount;
9365 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07009366 if (r.isForeground) {
9367 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
9368 }
9369 if (r.startRequested) {
9370 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
9371 }
Dan Egnor42471dd2010-01-07 17:25:22 -08009372 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -07009373 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
9374 }
9375 if (r.app != null && r.app.persistent) {
9376 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
9377 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009378
9379 for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
9380 for (int i=0; i<connl.size(); i++) {
9381 ConnectionRecord conn = connl.get(i);
9382 if (conn.clientLabel != 0) {
9383 info.clientPackage = conn.binding.client.info.packageName;
9384 info.clientLabel = conn.clientLabel;
9385 return info;
9386 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009387 }
9388 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009389 return info;
9390 }
9391
9392 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
9393 int flags) {
9394 synchronized (this) {
9395 ArrayList<ActivityManager.RunningServiceInfo> res
9396 = new ArrayList<ActivityManager.RunningServiceInfo>();
9397
9398 if (mServices.size() > 0) {
9399 Iterator<ServiceRecord> it = mServices.values().iterator();
9400 while (it.hasNext() && res.size() < maxNum) {
9401 res.add(makeRunningServiceInfoLocked(it.next()));
9402 }
9403 }
9404
9405 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
9406 ServiceRecord r = mRestartingServices.get(i);
9407 ActivityManager.RunningServiceInfo info =
9408 makeRunningServiceInfoLocked(r);
9409 info.restarting = r.nextRestartTime;
9410 res.add(info);
9411 }
9412
9413 return res;
9414 }
9415 }
9416
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009417 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
9418 synchronized (this) {
9419 ServiceRecord r = mServices.get(name);
9420 if (r != null) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009421 for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
9422 for (int i=0; i<conn.size(); i++) {
9423 if (conn.get(i).clientIntent != null) {
9424 return conn.get(i).clientIntent;
9425 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009426 }
9427 }
9428 }
9429 }
9430 return null;
9431 }
9432
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009433 private final ServiceRecord findServiceLocked(ComponentName name,
9434 IBinder token) {
9435 ServiceRecord r = mServices.get(name);
9436 return r == token ? r : null;
9437 }
9438
9439 private final class ServiceLookupResult {
9440 final ServiceRecord record;
9441 final String permission;
9442
9443 ServiceLookupResult(ServiceRecord _record, String _permission) {
9444 record = _record;
9445 permission = _permission;
9446 }
9447 };
9448
9449 private ServiceLookupResult findServiceLocked(Intent service,
9450 String resolvedType) {
9451 ServiceRecord r = null;
9452 if (service.getComponent() != null) {
9453 r = mServices.get(service.getComponent());
9454 }
9455 if (r == null) {
9456 Intent.FilterComparison filter = new Intent.FilterComparison(service);
9457 r = mServicesByIntent.get(filter);
9458 }
9459
9460 if (r == null) {
9461 try {
9462 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009463 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009464 service, resolvedType, 0);
9465 ServiceInfo sInfo =
9466 rInfo != null ? rInfo.serviceInfo : null;
9467 if (sInfo == null) {
9468 return null;
9469 }
9470
9471 ComponentName name = new ComponentName(
9472 sInfo.applicationInfo.packageName, sInfo.name);
9473 r = mServices.get(name);
9474 } catch (RemoteException ex) {
9475 // pm is in same process, this will never happen.
9476 }
9477 }
9478 if (r != null) {
9479 int callingPid = Binder.getCallingPid();
9480 int callingUid = Binder.getCallingUid();
9481 if (checkComponentPermission(r.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009482 callingPid, callingUid, r.appInfo.uid, r.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009483 != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009484 if (!r.exported) {
9485 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
9486 + " from pid=" + callingPid
9487 + ", uid=" + callingUid
9488 + " that is not exported from uid " + r.appInfo.uid);
9489 return new ServiceLookupResult(null, "not exported from uid "
9490 + r.appInfo.uid);
9491 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009492 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009493 + " from pid=" + callingPid
9494 + ", uid=" + callingUid
9495 + " requires " + r.permission);
9496 return new ServiceLookupResult(null, r.permission);
9497 }
9498 return new ServiceLookupResult(r, null);
9499 }
9500 return null;
9501 }
9502
9503 private class ServiceRestarter implements Runnable {
9504 private ServiceRecord mService;
9505
9506 void setService(ServiceRecord service) {
9507 mService = service;
9508 }
9509
9510 public void run() {
9511 synchronized(ActivityManagerService.this) {
9512 performServiceRestartLocked(mService);
9513 }
9514 }
9515 }
9516
9517 private ServiceLookupResult retrieveServiceLocked(Intent service,
9518 String resolvedType, int callingPid, int callingUid) {
9519 ServiceRecord r = null;
9520 if (service.getComponent() != null) {
9521 r = mServices.get(service.getComponent());
9522 }
9523 Intent.FilterComparison filter = new Intent.FilterComparison(service);
9524 r = mServicesByIntent.get(filter);
9525 if (r == null) {
9526 try {
9527 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009528 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -07009529 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009530 ServiceInfo sInfo =
9531 rInfo != null ? rInfo.serviceInfo : null;
9532 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009533 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009534 ": not found");
9535 return null;
9536 }
9537
9538 ComponentName name = new ComponentName(
9539 sInfo.applicationInfo.packageName, sInfo.name);
9540 r = mServices.get(name);
9541 if (r == null) {
9542 filter = new Intent.FilterComparison(service.cloneFilter());
9543 ServiceRestarter res = new ServiceRestarter();
9544 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
9545 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
9546 synchronized (stats) {
9547 ss = stats.getServiceStatsLocked(
9548 sInfo.applicationInfo.uid, sInfo.packageName,
9549 sInfo.name);
9550 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -08009551 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009552 res.setService(r);
9553 mServices.put(name, r);
9554 mServicesByIntent.put(filter, r);
9555
9556 // Make sure this component isn't in the pending list.
9557 int N = mPendingServices.size();
9558 for (int i=0; i<N; i++) {
9559 ServiceRecord pr = mPendingServices.get(i);
9560 if (pr.name.equals(name)) {
9561 mPendingServices.remove(i);
9562 i--;
9563 N--;
9564 }
9565 }
9566 }
9567 } catch (RemoteException ex) {
9568 // pm is in same process, this will never happen.
9569 }
9570 }
9571 if (r != null) {
9572 if (checkComponentPermission(r.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009573 callingPid, callingUid, r.appInfo.uid, r.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009574 != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009575 if (!r.exported) {
9576 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
9577 + " from pid=" + callingPid
9578 + ", uid=" + callingUid
9579 + " that is not exported from uid " + r.appInfo.uid);
9580 return new ServiceLookupResult(null, "not exported from uid "
9581 + r.appInfo.uid);
9582 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009583 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009584 + " from pid=" + callingPid
9585 + ", uid=" + callingUid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009586 + " requires " + r.permission);
9587 return new ServiceLookupResult(null, r.permission);
9588 }
9589 return new ServiceLookupResult(r, null);
9590 }
9591 return null;
9592 }
9593
Dianne Hackborn287952c2010-09-22 22:34:31 -07009594 private final void bumpServiceExecutingLocked(ServiceRecord r, String why) {
9595 if (DEBUG_SERVICE) Log.v(TAG, ">>> EXECUTING "
9596 + why + " of " + r + " in app " + r.app);
9597 else if (DEBUG_SERVICE_EXECUTING) Log.v(TAG, ">>> EXECUTING "
9598 + why + " of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009599 long now = SystemClock.uptimeMillis();
9600 if (r.executeNesting == 0 && r.app != null) {
9601 if (r.app.executingServices.size() == 0) {
9602 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
9603 msg.obj = r.app;
9604 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
9605 }
9606 r.app.executingServices.add(r);
9607 }
9608 r.executeNesting++;
9609 r.executingStart = now;
9610 }
9611
9612 private final void sendServiceArgsLocked(ServiceRecord r,
9613 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009614 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009615 if (N == 0) {
9616 return;
9617 }
9618
Dianne Hackborn39792d22010-08-19 18:01:52 -07009619 while (r.pendingStarts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009620 try {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009621 ServiceRecord.StartItem si = r.pendingStarts.remove(0);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009622 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
9623 + r + " " + r.intent + " args=" + si.intent);
Dianne Hackborn3a28f222011-03-01 12:25:54 -08009624 if (si.intent == null && N > 1) {
9625 // If somehow we got a dummy null intent in the middle,
9626 // then skip it. DO NOT skip a null intent when it is
9627 // the only one in the list -- this is to support the
9628 // onStartCommand(null) case.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009629 continue;
9630 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009631 si.deliveredTime = SystemClock.uptimeMillis();
9632 r.deliveredStarts.add(si);
9633 si.deliveryCount++;
Dianne Hackborn3a28f222011-03-01 12:25:54 -08009634 if (si.targetPermissionUid >= 0 && si.intent != null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009635 grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
Dianne Hackborn7e269642010-08-25 19:50:20 -07009636 r.packageName, si.intent, si.getUriPermissionsLocked());
Dianne Hackborn39792d22010-08-19 18:01:52 -07009637 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07009638 bumpServiceExecutingLocked(r, "start");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009639 if (!oomAdjusted) {
9640 oomAdjusted = true;
9641 updateOomAdjLocked(r.app);
9642 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009643 int flags = 0;
9644 if (si.deliveryCount > 0) {
9645 flags |= Service.START_FLAG_RETRY;
9646 }
9647 if (si.doneExecutingCount > 0) {
9648 flags |= Service.START_FLAG_REDELIVERY;
9649 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07009650 r.app.thread.scheduleServiceArgs(r, si.taskRemoved, si.id, flags, si.intent);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009651 } catch (RemoteException e) {
9652 // Remote process gone... we'll let the normal cleanup take
9653 // care of this.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009654 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009655 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009656 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009657 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009658 break;
9659 }
9660 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009661 }
9662
9663 private final boolean requestServiceBindingLocked(ServiceRecord r,
9664 IntentBindRecord i, boolean rebind) {
9665 if (r.app == null || r.app.thread == null) {
9666 // If service is not currently running, can't yet bind.
9667 return false;
9668 }
9669 if ((!i.requested || rebind) && i.apps.size() > 0) {
9670 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009671 bumpServiceExecutingLocked(r, "bind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009672 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
9673 if (!rebind) {
9674 i.requested = true;
9675 }
9676 i.hasBound = true;
9677 i.doRebind = false;
9678 } catch (RemoteException e) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009679 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009680 return false;
9681 }
9682 }
9683 return true;
9684 }
9685
9686 private final void requestServiceBindingsLocked(ServiceRecord r) {
9687 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
9688 while (bindings.hasNext()) {
9689 IntentBindRecord i = bindings.next();
9690 if (!requestServiceBindingLocked(r, i, false)) {
9691 break;
9692 }
9693 }
9694 }
9695
9696 private final void realStartServiceLocked(ServiceRecord r,
9697 ProcessRecord app) throws RemoteException {
9698 if (app.thread == null) {
9699 throw new RemoteException();
9700 }
9701
9702 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -07009703 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009704
9705 app.services.add(r);
Dianne Hackborn287952c2010-09-22 22:34:31 -07009706 bumpServiceExecutingLocked(r, "create");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009707 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009708
9709 boolean created = false;
9710 try {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07009711 mStringBuilder.setLength(0);
9712 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009713 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009714 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -07009715 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009716 synchronized (r.stats.getBatteryStats()) {
9717 r.stats.startLaunchedLocked();
9718 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07009719 ensurePackageDexOpt(r.serviceInfo.packageName);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04009720 app.thread.scheduleCreateService(r, r.serviceInfo,
9721 compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo));
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009722 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009723 created = true;
9724 } finally {
9725 if (!created) {
9726 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009727 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009728 }
9729 }
9730
9731 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009732
9733 // If the service is in the started state, and there are no
9734 // pending arguments, then fake up one so its onStartCommand() will
9735 // be called.
9736 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07009737 r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
9738 null, -1));
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009739 }
9740
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009741 sendServiceArgsLocked(r, true);
9742 }
9743
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009744 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
9745 boolean allowCancel) {
9746 boolean canceled = false;
9747
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009748 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009749 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -07009750 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009751
Dianne Hackborn070783f2010-12-29 16:46:28 -08009752 if ((r.serviceInfo.applicationInfo.flags
9753 &ApplicationInfo.FLAG_PERSISTENT) != 0) {
9754 minDuration /= 4;
9755 }
9756
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009757 // Any delivered but not yet finished starts should be put back
9758 // on the pending list.
9759 final int N = r.deliveredStarts.size();
9760 if (N > 0) {
9761 for (int i=N-1; i>=0; i--) {
9762 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
Dianne Hackborn39792d22010-08-19 18:01:52 -07009763 si.removeUriPermissionsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009764 if (si.intent == null) {
9765 // We'll generate this again if needed.
9766 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
9767 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
9768 r.pendingStarts.add(0, si);
9769 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
9770 dur *= 2;
9771 if (minDuration < dur) minDuration = dur;
9772 if (resetTime < dur) resetTime = dur;
9773 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009774 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009775 + r.name);
9776 canceled = true;
9777 }
9778 }
9779 r.deliveredStarts.clear();
9780 }
9781
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009782 r.totalRestartCount++;
9783 if (r.restartDelay == 0) {
9784 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009785 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009786 } else {
9787 // If it has been a "reasonably long time" since the service
9788 // was started, then reset our restart duration back to
9789 // the beginning, so we don't infinitely increase the duration
9790 // on a service that just occasionally gets killed (which is
9791 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009792 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009793 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009794 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009795 } else {
Dianne Hackborn070783f2010-12-29 16:46:28 -08009796 if ((r.serviceInfo.applicationInfo.flags
9797 &ApplicationInfo.FLAG_PERSISTENT) != 0) {
9798 // Services in peristent processes will restart much more
9799 // quickly, since they are pretty important. (Think SystemUI).
9800 r.restartDelay += minDuration/2;
9801 } else {
9802 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
9803 if (r.restartDelay < minDuration) {
9804 r.restartDelay = minDuration;
9805 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009806 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009807 }
9808 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009809
9810 r.nextRestartTime = now + r.restartDelay;
9811
9812 // Make sure that we don't end up restarting a bunch of services
9813 // all at the same time.
9814 boolean repeat;
9815 do {
9816 repeat = false;
9817 for (int i=mRestartingServices.size()-1; i>=0; i--) {
9818 ServiceRecord r2 = mRestartingServices.get(i);
9819 if (r2 != r && r.nextRestartTime
9820 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
9821 && r.nextRestartTime
9822 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
9823 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
9824 r.restartDelay = r.nextRestartTime - now;
9825 repeat = true;
9826 break;
9827 }
9828 }
9829 } while (repeat);
9830
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009831 if (!mRestartingServices.contains(r)) {
9832 mRestartingServices.add(r);
9833 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009834
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009835 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009836
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009837 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009838 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009839 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009840 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009841 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -08009842 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009843 r.shortName, r.restartDelay);
9844
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009845 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009846 }
9847
9848 final void performServiceRestartLocked(ServiceRecord r) {
9849 if (!mRestartingServices.contains(r)) {
9850 return;
9851 }
9852 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
9853 }
9854
9855 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
9856 if (r.restartDelay == 0) {
9857 return false;
9858 }
9859 r.resetRestartCounter();
9860 mRestartingServices.remove(r);
9861 mHandler.removeCallbacks(r.restarter);
9862 return true;
9863 }
9864
9865 private final boolean bringUpServiceLocked(ServiceRecord r,
9866 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009867 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009868 //r.dump(" ");
9869
Dianne Hackborn36124872009-10-08 16:22:03 -07009870 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009871 sendServiceArgsLocked(r, false);
9872 return true;
9873 }
9874
9875 if (!whileRestarting && r.restartDelay > 0) {
9876 // If waiting for a restart, then do nothing.
9877 return true;
9878 }
9879
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009880 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009881
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009882 // We are now bringing the service up, so no longer in the
9883 // restarting state.
9884 mRestartingServices.remove(r);
9885
Dianne Hackborne7f97212011-02-24 14:40:20 -08009886 // Service is now being launched, its package can't be stopped.
9887 try {
9888 AppGlobals.getPackageManager().setPackageStoppedState(
9889 r.packageName, false);
9890 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08009891 } catch (IllegalArgumentException e) {
9892 Slog.w(TAG, "Failed trying to unstop package "
9893 + r.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08009894 }
9895
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009896 final String appName = r.processName;
9897 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
9898 if (app != null && app.thread != null) {
9899 try {
Dianne Hackborn6c418d52011-06-29 14:05:33 -07009900 app.addPackage(r.appInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009901 realStartServiceLocked(r, app);
9902 return true;
9903 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009904 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009905 }
9906
9907 // If a dead object exception was thrown -- fall through to
9908 // restart the application.
9909 }
9910
Dianne Hackborn36124872009-10-08 16:22:03 -07009911 // Not running -- get it started, and enqueue this service record
9912 // to be executed when the app comes up.
9913 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
9914 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009915 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -07009916 + r.appInfo.packageName + "/"
9917 + r.appInfo.uid + " for service "
9918 + r.intent.getIntent() + ": process is bad");
9919 bringDownServiceLocked(r, true);
9920 return false;
9921 }
9922
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009923 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009924 mPendingServices.add(r);
9925 }
Dianne Hackborn36124872009-10-08 16:22:03 -07009926
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009927 return true;
9928 }
9929
9930 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009931 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009932 //r.dump(" ");
9933
9934 // Does it still need to run?
9935 if (!force && r.startRequested) {
9936 return;
9937 }
9938 if (r.connections.size() > 0) {
9939 if (!force) {
9940 // XXX should probably keep a count of the number of auto-create
9941 // connections directly in the service.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009942 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009943 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009944 ArrayList<ConnectionRecord> cr = it.next();
9945 for (int i=0; i<cr.size(); i++) {
9946 if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
9947 return;
9948 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009949 }
9950 }
9951 }
9952
9953 // Report to all of the connections that the service is no longer
9954 // available.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009955 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009956 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009957 ArrayList<ConnectionRecord> c = it.next();
9958 for (int i=0; i<c.size(); i++) {
9959 try {
9960 c.get(i).conn.connected(r.name, null);
9961 } catch (Exception e) {
9962 Slog.w(TAG, "Failure disconnecting service " + r.name +
9963 " to connection " + c.get(i).conn.asBinder() +
9964 " (in " + c.get(i).binding.client.processName + ")", e);
9965 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009966 }
9967 }
9968 }
9969
9970 // Tell the service that it has been unbound.
9971 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
9972 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
9973 while (it.hasNext()) {
9974 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009975 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009976 + ": hasBound=" + ibr.hasBound);
9977 if (r.app != null && r.app.thread != null && ibr.hasBound) {
9978 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009979 bumpServiceExecutingLocked(r, "bring down unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009980 updateOomAdjLocked(r.app);
9981 ibr.hasBound = false;
9982 r.app.thread.scheduleUnbindService(r,
9983 ibr.intent.getIntent());
9984 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009985 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009986 + r.shortName, e);
9987 serviceDoneExecutingLocked(r, true);
9988 }
9989 }
9990 }
9991 }
9992
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009993 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009994 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009995 System.identityHashCode(r), r.shortName,
9996 (r.app != null) ? r.app.pid : -1);
9997
9998 mServices.remove(r.name);
9999 mServicesByIntent.remove(r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010000 r.totalRestartCount = 0;
10001 unscheduleServiceRestartLocked(r);
10002
10003 // Also make sure it is not on the pending list.
10004 int N = mPendingServices.size();
10005 for (int i=0; i<N; i++) {
10006 if (mPendingServices.get(i) == r) {
10007 mPendingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010008 if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010009 i--;
10010 N--;
10011 }
10012 }
10013
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010014 r.cancelNotification();
10015 r.isForeground = false;
10016 r.foregroundId = 0;
10017 r.foregroundNoti = null;
10018
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010019 // Clear start entries.
Dianne Hackborn39792d22010-08-19 18:01:52 -070010020 r.clearDeliveredStartsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010021 r.pendingStarts.clear();
10022
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010023 if (r.app != null) {
10024 synchronized (r.stats.getBatteryStats()) {
10025 r.stats.stopLaunchedLocked();
10026 }
10027 r.app.services.remove(r);
10028 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010029 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010030 bumpServiceExecutingLocked(r, "stop");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010031 mStoppingServices.add(r);
10032 updateOomAdjLocked(r.app);
10033 r.app.thread.scheduleStopService(r);
10034 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010035 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010036 + r.shortName, e);
10037 serviceDoneExecutingLocked(r, true);
10038 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010039 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010040 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010041 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010042 TAG, "Removed service that has no process: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010043 }
10044 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010045 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010046 TAG, "Removed service that is not running: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010047 }
Vairavan Srinivasana207ce22010-12-23 13:51:48 -080010048
10049 if (r.bindings.size() > 0) {
10050 r.bindings.clear();
10051 }
10052
10053 if (r.restarter instanceof ServiceRestarter) {
10054 ((ServiceRestarter)r.restarter).setService(null);
10055 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010056 }
10057
10058 ComponentName startServiceLocked(IApplicationThread caller,
10059 Intent service, String resolvedType,
10060 int callingPid, int callingUid) {
10061 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010062 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010063 + " type=" + resolvedType + " args=" + service.getExtras());
10064
10065 if (caller != null) {
10066 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10067 if (callerApp == null) {
10068 throw new SecurityException(
10069 "Unable to find app for caller " + caller
10070 + " (pid=" + Binder.getCallingPid()
10071 + ") when starting service " + service);
10072 }
10073 }
10074
10075 ServiceLookupResult res =
10076 retrieveServiceLocked(service, resolvedType,
10077 callingPid, callingUid);
10078 if (res == null) {
10079 return null;
10080 }
10081 if (res.record == null) {
10082 return new ComponentName("!", res.permission != null
10083 ? res.permission : "private to package");
10084 }
10085 ServiceRecord r = res.record;
Dianne Hackborn39792d22010-08-19 18:01:52 -070010086 int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
10087 callingUid, r.packageName, service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010088 if (unscheduleServiceRestartLocked(r)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010089 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010090 }
10091 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010092 r.callStart = false;
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010093 r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
Dianne Hackborn39792d22010-08-19 18:01:52 -070010094 service, targetPermissionUid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010095 r.lastActivity = SystemClock.uptimeMillis();
10096 synchronized (r.stats.getBatteryStats()) {
10097 r.stats.startRunningLocked();
10098 }
10099 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
10100 return new ComponentName("!", "Service process is bad");
10101 }
10102 return r.name;
10103 }
10104 }
10105
10106 public ComponentName startService(IApplicationThread caller, Intent service,
10107 String resolvedType) {
10108 // Refuse possible leaked file descriptors
10109 if (service != null && service.hasFileDescriptors() == true) {
10110 throw new IllegalArgumentException("File descriptors passed in Intent");
10111 }
10112
10113 synchronized(this) {
10114 final int callingPid = Binder.getCallingPid();
10115 final int callingUid = Binder.getCallingUid();
10116 final long origId = Binder.clearCallingIdentity();
10117 ComponentName res = startServiceLocked(caller, service,
10118 resolvedType, callingPid, callingUid);
10119 Binder.restoreCallingIdentity(origId);
10120 return res;
10121 }
10122 }
10123
10124 ComponentName startServiceInPackage(int uid,
10125 Intent service, String resolvedType) {
10126 synchronized(this) {
10127 final long origId = Binder.clearCallingIdentity();
10128 ComponentName res = startServiceLocked(null, service,
10129 resolvedType, -1, uid);
10130 Binder.restoreCallingIdentity(origId);
10131 return res;
10132 }
10133 }
10134
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010135 private void stopServiceLocked(ServiceRecord service) {
10136 synchronized (service.stats.getBatteryStats()) {
10137 service.stats.stopRunningLocked();
10138 }
10139 service.startRequested = false;
10140 service.callStart = false;
10141 bringDownServiceLocked(service, false);
10142 }
10143
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010144 public int stopService(IApplicationThread caller, Intent service,
10145 String resolvedType) {
10146 // Refuse possible leaked file descriptors
10147 if (service != null && service.hasFileDescriptors() == true) {
10148 throw new IllegalArgumentException("File descriptors passed in Intent");
10149 }
10150
10151 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010152 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010153 + " type=" + resolvedType);
10154
10155 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10156 if (caller != null && callerApp == null) {
10157 throw new SecurityException(
10158 "Unable to find app for caller " + caller
10159 + " (pid=" + Binder.getCallingPid()
10160 + ") when stopping service " + service);
10161 }
10162
10163 // If this service is active, make sure it is stopped.
10164 ServiceLookupResult r = findServiceLocked(service, resolvedType);
10165 if (r != null) {
10166 if (r.record != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010167 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010168 try {
10169 stopServiceLocked(r.record);
10170 } finally {
10171 Binder.restoreCallingIdentity(origId);
10172 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010173 return 1;
10174 }
10175 return -1;
10176 }
10177 }
10178
10179 return 0;
10180 }
10181
10182 public IBinder peekService(Intent service, String resolvedType) {
10183 // Refuse possible leaked file descriptors
10184 if (service != null && service.hasFileDescriptors() == true) {
10185 throw new IllegalArgumentException("File descriptors passed in Intent");
10186 }
10187
10188 IBinder ret = null;
10189
10190 synchronized(this) {
10191 ServiceLookupResult r = findServiceLocked(service, resolvedType);
10192
10193 if (r != null) {
10194 // r.record is null if findServiceLocked() failed the caller permission check
10195 if (r.record == null) {
10196 throw new SecurityException(
10197 "Permission Denial: Accessing service " + r.record.name
10198 + " from pid=" + Binder.getCallingPid()
10199 + ", uid=" + Binder.getCallingUid()
10200 + " requires " + r.permission);
10201 }
10202 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
10203 if (ib != null) {
10204 ret = ib.binder;
10205 }
10206 }
10207 }
10208
10209 return ret;
10210 }
10211
10212 public boolean stopServiceToken(ComponentName className, IBinder token,
10213 int startId) {
10214 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010215 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010216 + " " + token + " startId=" + startId);
10217 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010218 if (r != null) {
10219 if (startId >= 0) {
10220 // Asked to only stop if done with all work. Note that
10221 // to avoid leaks, we will take this as dropping all
10222 // start items up to and including this one.
10223 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
10224 if (si != null) {
10225 while (r.deliveredStarts.size() > 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -070010226 ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
10227 cur.removeUriPermissionsLocked();
10228 if (cur == si) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010229 break;
10230 }
10231 }
10232 }
10233
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010234 if (r.getLastStartId() != startId) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010235 return false;
10236 }
10237
10238 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010239 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010240 + " is last, but have " + r.deliveredStarts.size()
10241 + " remaining args");
10242 }
10243 }
10244
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010245 synchronized (r.stats.getBatteryStats()) {
10246 r.stats.stopRunningLocked();
10247 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010248 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010249 }
10250 final long origId = Binder.clearCallingIdentity();
10251 bringDownServiceLocked(r, false);
10252 Binder.restoreCallingIdentity(origId);
10253 return true;
10254 }
10255 }
10256 return false;
10257 }
10258
10259 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010260 int id, Notification notification, boolean removeNotification) {
10261 final long origId = Binder.clearCallingIdentity();
10262 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010263 synchronized(this) {
10264 ServiceRecord r = findServiceLocked(className, token);
10265 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010266 if (id != 0) {
10267 if (notification == null) {
10268 throw new IllegalArgumentException("null notification");
10269 }
10270 if (r.foregroundId != id) {
10271 r.cancelNotification();
10272 r.foregroundId = id;
10273 }
10274 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
10275 r.foregroundNoti = notification;
10276 r.isForeground = true;
10277 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010278 if (r.app != null) {
10279 updateServiceForegroundLocked(r.app, true);
10280 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010281 } else {
10282 if (r.isForeground) {
10283 r.isForeground = false;
10284 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -070010285 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010286 updateServiceForegroundLocked(r.app, true);
10287 }
10288 }
10289 if (removeNotification) {
10290 r.cancelNotification();
10291 r.foregroundId = 0;
10292 r.foregroundNoti = null;
10293 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010294 }
10295 }
10296 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010297 } finally {
10298 Binder.restoreCallingIdentity(origId);
10299 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010300 }
10301
10302 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
10303 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -070010304 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010305 if (sr.isForeground) {
10306 anyForeground = true;
10307 break;
10308 }
10309 }
10310 if (anyForeground != proc.foregroundServices) {
10311 proc.foregroundServices = anyForeground;
10312 if (oomAdj) {
10313 updateOomAdjLocked();
10314 }
10315 }
10316 }
10317
10318 public int bindService(IApplicationThread caller, IBinder token,
10319 Intent service, String resolvedType,
10320 IServiceConnection connection, int flags) {
10321 // Refuse possible leaked file descriptors
10322 if (service != null && service.hasFileDescriptors() == true) {
10323 throw new IllegalArgumentException("File descriptors passed in Intent");
10324 }
10325
10326 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010327 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010328 + " type=" + resolvedType + " conn=" + connection.asBinder()
10329 + " flags=0x" + Integer.toHexString(flags));
10330 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10331 if (callerApp == null) {
10332 throw new SecurityException(
10333 "Unable to find app for caller " + caller
10334 + " (pid=" + Binder.getCallingPid()
10335 + ") when binding service " + service);
10336 }
10337
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010338 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010339 if (token != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010340 int aindex = mMainStack.indexOfTokenLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010341 if (aindex < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010342 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010343 return 0;
10344 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010345 activity = (ActivityRecord)mMainStack.mHistory.get(aindex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010346 }
10347
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010348 int clientLabel = 0;
10349 PendingIntent clientIntent = null;
10350
10351 if (callerApp.info.uid == Process.SYSTEM_UID) {
10352 // Hacky kind of thing -- allow system stuff to tell us
10353 // what they are, so we can report this elsewhere for
10354 // others to know why certain services are running.
10355 try {
10356 clientIntent = (PendingIntent)service.getParcelableExtra(
10357 Intent.EXTRA_CLIENT_INTENT);
10358 } catch (RuntimeException e) {
10359 }
10360 if (clientIntent != null) {
10361 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
10362 if (clientLabel != 0) {
10363 // There are no useful extras in the intent, trash them.
10364 // System code calling with this stuff just needs to know
10365 // this will happen.
10366 service = service.cloneFilter();
10367 }
10368 }
10369 }
10370
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010371 ServiceLookupResult res =
10372 retrieveServiceLocked(service, resolvedType,
10373 Binder.getCallingPid(), Binder.getCallingUid());
10374 if (res == null) {
10375 return 0;
10376 }
10377 if (res.record == null) {
10378 return -1;
10379 }
10380 ServiceRecord s = res.record;
10381
10382 final long origId = Binder.clearCallingIdentity();
10383
10384 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010385 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010386 + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010387 }
10388
10389 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
10390 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010391 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010392
10393 IBinder binder = connection.asBinder();
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010394 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
10395 if (clist == null) {
10396 clist = new ArrayList<ConnectionRecord>();
10397 s.connections.put(binder, clist);
10398 }
10399 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010400 b.connections.add(c);
10401 if (activity != null) {
10402 if (activity.connections == null) {
10403 activity.connections = new HashSet<ConnectionRecord>();
10404 }
10405 activity.connections.add(c);
10406 }
10407 b.client.connections.add(c);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010408 clist = mServiceConnections.get(binder);
10409 if (clist == null) {
10410 clist = new ArrayList<ConnectionRecord>();
10411 mServiceConnections.put(binder, clist);
10412 }
10413 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010414
10415 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
10416 s.lastActivity = SystemClock.uptimeMillis();
10417 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
10418 return 0;
10419 }
10420 }
10421
10422 if (s.app != null) {
10423 // This could have made the service more important.
10424 updateOomAdjLocked(s.app);
10425 }
10426
Joe Onorato8a9b2202010-02-26 18:56:32 -080010427 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010428 + ": received=" + b.intent.received
10429 + " apps=" + b.intent.apps.size()
10430 + " doRebind=" + b.intent.doRebind);
10431
10432 if (s.app != null && b.intent.received) {
10433 // Service is already running, so we can immediately
10434 // publish the connection.
10435 try {
10436 c.conn.connected(s.name, b.intent.binder);
10437 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010438 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010439 + " to connection " + c.conn.asBinder()
10440 + " (in " + c.binding.client.processName + ")", e);
10441 }
10442
10443 // If this is the first app connected back to this binding,
10444 // and the service had previously asked to be told when
10445 // rebound, then do so.
10446 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
10447 requestServiceBindingLocked(s, b.intent, true);
10448 }
10449 } else if (!b.intent.requested) {
10450 requestServiceBindingLocked(s, b.intent, false);
10451 }
10452
10453 Binder.restoreCallingIdentity(origId);
10454 }
10455
10456 return 1;
10457 }
10458
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010459 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010460 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010461 IBinder binder = c.conn.asBinder();
10462 AppBindRecord b = c.binding;
10463 ServiceRecord s = b.service;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010464 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
10465 if (clist != null) {
10466 clist.remove(c);
10467 if (clist.size() == 0) {
10468 s.connections.remove(binder);
10469 }
10470 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010471 b.connections.remove(c);
10472 if (c.activity != null && c.activity != skipAct) {
10473 if (c.activity.connections != null) {
10474 c.activity.connections.remove(c);
10475 }
10476 }
10477 if (b.client != skipApp) {
10478 b.client.connections.remove(c);
10479 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010480 clist = mServiceConnections.get(binder);
10481 if (clist != null) {
10482 clist.remove(c);
10483 if (clist.size() == 0) {
10484 mServiceConnections.remove(binder);
10485 }
10486 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010487
10488 if (b.connections.size() == 0) {
10489 b.intent.apps.remove(b.client);
10490 }
10491
Joe Onorato8a9b2202010-02-26 18:56:32 -080010492 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010493 + ": shouldUnbind=" + b.intent.hasBound);
10494 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
10495 && b.intent.hasBound) {
10496 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010497 bumpServiceExecutingLocked(s, "unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010498 updateOomAdjLocked(s.app);
10499 b.intent.hasBound = false;
10500 // Assume the client doesn't want to know about a rebind;
10501 // we will deal with that later if it asks for one.
10502 b.intent.doRebind = false;
10503 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
10504 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010505 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010506 serviceDoneExecutingLocked(s, true);
10507 }
10508 }
10509
10510 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
10511 bringDownServiceLocked(s, false);
10512 }
10513 }
10514
10515 public boolean unbindService(IServiceConnection connection) {
10516 synchronized (this) {
10517 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010518 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010519 ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
10520 if (clist == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010521 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010522 + connection.asBinder());
10523 return false;
10524 }
10525
10526 final long origId = Binder.clearCallingIdentity();
10527
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010528 while (clist.size() > 0) {
10529 ConnectionRecord r = clist.get(0);
10530 removeConnectionLocked(r, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010531
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010532 if (r.binding.service.app != null) {
10533 // This could have made the service less important.
10534 updateOomAdjLocked(r.binding.service.app);
10535 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010536 }
10537
10538 Binder.restoreCallingIdentity(origId);
10539 }
10540
10541 return true;
10542 }
10543
10544 public void publishService(IBinder token, Intent intent, IBinder service) {
10545 // Refuse possible leaked file descriptors
10546 if (intent != null && intent.hasFileDescriptors() == true) {
10547 throw new IllegalArgumentException("File descriptors passed in Intent");
10548 }
10549
10550 synchronized(this) {
10551 if (!(token instanceof ServiceRecord)) {
10552 throw new IllegalArgumentException("Invalid service token");
10553 }
10554 ServiceRecord r = (ServiceRecord)token;
10555
10556 final long origId = Binder.clearCallingIdentity();
10557
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010558 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010559 + " " + intent + ": " + service);
10560 if (r != null) {
10561 Intent.FilterComparison filter
10562 = new Intent.FilterComparison(intent);
10563 IntentBindRecord b = r.bindings.get(filter);
10564 if (b != null && !b.received) {
10565 b.binder = service;
10566 b.requested = true;
10567 b.received = true;
10568 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010569 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010570 = r.connections.values().iterator();
10571 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010572 ArrayList<ConnectionRecord> clist = it.next();
10573 for (int i=0; i<clist.size(); i++) {
10574 ConnectionRecord c = clist.get(i);
10575 if (!filter.equals(c.binding.intent.intent)) {
10576 if (DEBUG_SERVICE) Slog.v(
10577 TAG, "Not publishing to: " + c);
10578 if (DEBUG_SERVICE) Slog.v(
10579 TAG, "Bound intent: " + c.binding.intent.intent);
10580 if (DEBUG_SERVICE) Slog.v(
10581 TAG, "Published intent: " + intent);
10582 continue;
10583 }
10584 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
10585 try {
10586 c.conn.connected(r.name, service);
10587 } catch (Exception e) {
10588 Slog.w(TAG, "Failure sending service " + r.name +
10589 " to connection " + c.conn.asBinder() +
10590 " (in " + c.binding.client.processName + ")", e);
10591 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010592 }
10593 }
10594 }
10595 }
10596
10597 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
10598
10599 Binder.restoreCallingIdentity(origId);
10600 }
10601 }
10602 }
10603
10604 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
10605 // Refuse possible leaked file descriptors
10606 if (intent != null && intent.hasFileDescriptors() == true) {
10607 throw new IllegalArgumentException("File descriptors passed in Intent");
10608 }
10609
10610 synchronized(this) {
10611 if (!(token instanceof ServiceRecord)) {
10612 throw new IllegalArgumentException("Invalid service token");
10613 }
10614 ServiceRecord r = (ServiceRecord)token;
10615
10616 final long origId = Binder.clearCallingIdentity();
10617
10618 if (r != null) {
10619 Intent.FilterComparison filter
10620 = new Intent.FilterComparison(intent);
10621 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010622 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010623 + " at " + b + ": apps="
10624 + (b != null ? b.apps.size() : 0));
10625 if (b != null) {
10626 if (b.apps.size() > 0) {
10627 // Applications have already bound since the last
10628 // unbind, so just rebind right here.
10629 requestServiceBindingLocked(r, b, true);
10630 } else {
10631 // Note to tell the service the next time there is
10632 // a new client.
10633 b.doRebind = true;
10634 }
10635 }
10636
10637 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
10638
10639 Binder.restoreCallingIdentity(origId);
10640 }
10641 }
10642 }
10643
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010644 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010645 synchronized(this) {
10646 if (!(token instanceof ServiceRecord)) {
10647 throw new IllegalArgumentException("Invalid service token");
10648 }
10649 ServiceRecord r = (ServiceRecord)token;
10650 boolean inStopping = mStoppingServices.contains(token);
10651 if (r != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010652 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010653 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010654 + " with incorrect token: given " + token
10655 + ", expected " + r);
10656 return;
10657 }
10658
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010659 if (type == 1) {
10660 // This is a call from a service start... take care of
10661 // book-keeping.
10662 r.callStart = true;
10663 switch (res) {
10664 case Service.START_STICKY_COMPATIBILITY:
10665 case Service.START_STICKY: {
10666 // We are done with the associated start arguments.
10667 r.findDeliveredStart(startId, true);
10668 // Don't stop if killed.
10669 r.stopIfKilled = false;
10670 break;
10671 }
10672 case Service.START_NOT_STICKY: {
10673 // We are done with the associated start arguments.
10674 r.findDeliveredStart(startId, true);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010675 if (r.getLastStartId() == startId) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010676 // There is no more work, and this service
10677 // doesn't want to hang around if killed.
10678 r.stopIfKilled = true;
10679 }
10680 break;
10681 }
10682 case Service.START_REDELIVER_INTENT: {
10683 // We'll keep this item until they explicitly
10684 // call stop for it, but keep track of the fact
10685 // that it was delivered.
10686 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
10687 if (si != null) {
10688 si.deliveryCount = 0;
10689 si.doneExecutingCount++;
10690 // Don't stop if killed.
10691 r.stopIfKilled = true;
10692 }
10693 break;
10694 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010695 case Service.START_TASK_REMOVED_COMPLETE: {
10696 // Special processing for onTaskRemoved(). Don't
10697 // impact normal onStartCommand() processing.
10698 r.findDeliveredStart(startId, true);
10699 break;
10700 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010701 default:
10702 throw new IllegalArgumentException(
10703 "Unknown service start result: " + res);
10704 }
10705 if (res == Service.START_STICKY_COMPATIBILITY) {
10706 r.callStart = false;
10707 }
10708 }
10709
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010710 final long origId = Binder.clearCallingIdentity();
10711 serviceDoneExecutingLocked(r, inStopping);
10712 Binder.restoreCallingIdentity(origId);
10713 } else {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010714 Slog.w(TAG, "Done executing unknown service from pid "
10715 + Binder.getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010716 }
10717 }
10718 }
10719
10720 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010721 if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
10722 + ": nesting=" + r.executeNesting
10723 + ", inStopping=" + inStopping + ", app=" + r.app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070010724 else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010725 r.executeNesting--;
10726 if (r.executeNesting <= 0 && r.app != null) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010727 if (DEBUG_SERVICE) Slog.v(TAG,
10728 "Nesting at 0 of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010729 r.app.executingServices.remove(r);
10730 if (r.app.executingServices.size() == 0) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010731 if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,
10732 "No more executingServices of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010733 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
10734 }
10735 if (inStopping) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010736 if (DEBUG_SERVICE) Slog.v(TAG,
10737 "doneExecuting remove stopping " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010738 mStoppingServices.remove(r);
Mattias Petersson3996b412010-10-27 09:32:51 +020010739 r.bindings.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010740 }
10741 updateOomAdjLocked(r.app);
10742 }
10743 }
10744
10745 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010746 String anrMessage = null;
10747
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010748 synchronized(this) {
10749 if (proc.executingServices.size() == 0 || proc.thread == null) {
10750 return;
10751 }
10752 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
10753 Iterator<ServiceRecord> it = proc.executingServices.iterator();
10754 ServiceRecord timeout = null;
10755 long nextTime = 0;
10756 while (it.hasNext()) {
10757 ServiceRecord sr = it.next();
10758 if (sr.executingStart < maxTime) {
10759 timeout = sr;
10760 break;
10761 }
10762 if (sr.executingStart > nextTime) {
10763 nextTime = sr.executingStart;
10764 }
10765 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010766 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010767 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010768 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010769 } else {
10770 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
10771 msg.obj = proc;
10772 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
10773 }
10774 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010775
10776 if (anrMessage != null) {
10777 appNotResponding(proc, null, null, anrMessage);
10778 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010779 }
10780
10781 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070010782 // BACKUP AND RESTORE
10783 // =========================================================
10784
10785 // Cause the target app to be launched if necessary and its backup agent
10786 // instantiated. The backup agent will invoke backupAgentCreated() on the
10787 // activity manager to announce its creation.
10788 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010789 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070010790 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
10791
10792 synchronized(this) {
10793 // !!! TODO: currently no check here that we're already bound
10794 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
10795 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
10796 synchronized (stats) {
10797 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
10798 }
10799
Dianne Hackborne7f97212011-02-24 14:40:20 -080010800 // Backup agent is now in use, its package can't be stopped.
10801 try {
10802 AppGlobals.getPackageManager().setPackageStoppedState(
10803 app.packageName, false);
10804 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -080010805 } catch (IllegalArgumentException e) {
10806 Slog.w(TAG, "Failed trying to unstop package "
10807 + app.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -080010808 }
10809
Christopher Tate181fafa2009-05-14 11:12:14 -070010810 BackupRecord r = new BackupRecord(ss, app, backupMode);
Christopher Tate4a627c72011-04-01 14:43:32 -070010811 ComponentName hostingName = (backupMode == IApplicationThread.BACKUP_MODE_INCREMENTAL)
10812 ? new ComponentName(app.packageName, app.backupAgentName)
10813 : new ComponentName("android", "FullBackupAgent");
Christopher Tate181fafa2009-05-14 11:12:14 -070010814 // startProcessLocked() returns existing proc's record if it's already running
10815 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010816 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070010817 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010818 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070010819 return false;
10820 }
10821
10822 r.app = proc;
10823 mBackupTarget = r;
10824 mBackupAppName = app.packageName;
10825
Christopher Tate6fa95972009-06-05 18:43:55 -070010826 // Try not to kill the process during backup
10827 updateOomAdjLocked(proc);
10828
Christopher Tate181fafa2009-05-14 11:12:14 -070010829 // If the process is already attached, schedule the creation of the backup agent now.
10830 // If it is not yet live, this will be done when it attaches to the framework.
10831 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010832 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070010833 try {
Dianne Hackborne2515ee2011-04-27 18:52:56 -040010834 proc.thread.scheduleCreateBackupAgent(app,
10835 compatibilityInfoForPackageLocked(app), backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070010836 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070010837 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070010838 }
10839 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010840 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070010841 }
10842 // Invariants: at this point, the target app process exists and the application
10843 // is either already running or in the process of coming up. mBackupTarget and
10844 // mBackupAppName describe the app, so that when it binds back to the AM we
10845 // know that it's scheduled for a backup-agent operation.
10846 }
10847
10848 return true;
10849 }
10850
10851 // A backup agent has just come up
10852 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010853 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070010854 + " = " + agent);
10855
10856 synchronized(this) {
10857 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010858 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070010859 return;
10860 }
Dianne Hackborn06740692010-09-22 22:46:21 -070010861 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010862
Dianne Hackborn06740692010-09-22 22:46:21 -070010863 long oldIdent = Binder.clearCallingIdentity();
10864 try {
10865 IBackupManager bm = IBackupManager.Stub.asInterface(
10866 ServiceManager.getService(Context.BACKUP_SERVICE));
10867 bm.agentConnected(agentPackageName, agent);
10868 } catch (RemoteException e) {
10869 // can't happen; the backup manager service is local
10870 } catch (Exception e) {
10871 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
10872 e.printStackTrace();
10873 } finally {
10874 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070010875 }
10876 }
10877
10878 // done with this agent
10879 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010880 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070010881 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010882 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070010883 return;
10884 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010885
10886 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070010887 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010888 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070010889 return;
10890 }
10891
Christopher Tate181fafa2009-05-14 11:12:14 -070010892 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010893 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070010894 return;
10895 }
10896
Christopher Tate6fa95972009-06-05 18:43:55 -070010897 ProcessRecord proc = mBackupTarget.app;
10898 mBackupTarget = null;
10899 mBackupAppName = null;
10900
10901 // Not backing this app up any more; reset its OOM adjustment
10902 updateOomAdjLocked(proc);
10903
Christopher Tatec7b31e32009-06-10 15:49:30 -070010904 // If the app crashed during backup, 'thread' will be null here
10905 if (proc.thread != null) {
10906 try {
Dianne Hackborne2515ee2011-04-27 18:52:56 -040010907 proc.thread.scheduleDestroyBackupAgent(appInfo,
10908 compatibilityInfoForPackageLocked(appInfo));
Christopher Tatec7b31e32009-06-10 15:49:30 -070010909 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010910 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070010911 e.printStackTrace();
10912 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010913 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010914 }
10915 }
10916 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010917 // BROADCASTS
10918 // =========================================================
10919
Josh Bartel7f208742010-02-25 11:01:44 -060010920 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010921 List cur) {
10922 final ContentResolver resolver = mContext.getContentResolver();
10923 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
10924 if (list == null) {
10925 return cur;
10926 }
10927 int N = list.size();
10928 for (int i=0; i<N; i++) {
10929 Intent intent = list.get(i);
10930 if (filter.match(resolver, intent, true, TAG) >= 0) {
10931 if (cur == null) {
10932 cur = new ArrayList<Intent>();
10933 }
10934 cur.add(intent);
10935 }
10936 }
10937 return cur;
10938 }
10939
10940 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010941 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010942 + mBroadcastsScheduled);
10943
10944 if (mBroadcastsScheduled) {
10945 return;
10946 }
10947 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
10948 mBroadcastsScheduled = true;
10949 }
10950
Dianne Hackborn6c418d52011-06-29 14:05:33 -070010951 public Intent registerReceiver(IApplicationThread caller, String callerPackage,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010952 IIntentReceiver receiver, IntentFilter filter, String permission) {
10953 synchronized(this) {
10954 ProcessRecord callerApp = null;
10955 if (caller != null) {
10956 callerApp = getRecordForAppLocked(caller);
10957 if (callerApp == null) {
10958 throw new SecurityException(
10959 "Unable to find app for caller " + caller
10960 + " (pid=" + Binder.getCallingPid()
10961 + ") when registering receiver " + receiver);
10962 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -070010963 if (callerApp.info.uid != Process.SYSTEM_UID &&
10964 !callerApp.pkgList.contains(callerPackage)) {
10965 throw new SecurityException("Given caller package " + callerPackage
10966 + " is not running in process " + callerApp);
10967 }
10968 } else {
10969 callerPackage = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010970 }
10971
10972 List allSticky = null;
10973
10974 // Look for any matching sticky broadcasts...
10975 Iterator actions = filter.actionsIterator();
10976 if (actions != null) {
10977 while (actions.hasNext()) {
10978 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -060010979 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010980 }
10981 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060010982 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010983 }
10984
10985 // The first sticky in the list is returned directly back to
10986 // the client.
10987 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
10988
Joe Onorato8a9b2202010-02-26 18:56:32 -080010989 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010990 + ": " + sticky);
10991
10992 if (receiver == null) {
10993 return sticky;
10994 }
10995
10996 ReceiverList rl
10997 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
10998 if (rl == null) {
10999 rl = new ReceiverList(this, callerApp,
11000 Binder.getCallingPid(),
11001 Binder.getCallingUid(), receiver);
11002 if (rl.app != null) {
11003 rl.app.receivers.add(rl);
11004 } else {
11005 try {
11006 receiver.asBinder().linkToDeath(rl, 0);
11007 } catch (RemoteException e) {
11008 return sticky;
11009 }
11010 rl.linkedToDeath = true;
11011 }
11012 mRegisteredReceivers.put(receiver.asBinder(), rl);
11013 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -070011014 BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage, permission);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011015 rl.add(bf);
11016 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011017 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011018 }
11019 mReceiverResolver.addFilter(bf);
11020
11021 // Enqueue broadcasts for all existing stickies that match
11022 // this filter.
11023 if (allSticky != null) {
11024 ArrayList receivers = new ArrayList();
11025 receivers.add(bf);
11026
11027 int N = allSticky.size();
11028 for (int i=0; i<N; i++) {
11029 Intent intent = (Intent)allSticky.get(i);
11030 BroadcastRecord r = new BroadcastRecord(intent, null,
11031 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011032 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011033 if (mParallelBroadcasts.size() == 0) {
11034 scheduleBroadcastsLocked();
11035 }
11036 mParallelBroadcasts.add(r);
11037 }
11038 }
11039
11040 return sticky;
11041 }
11042 }
11043
11044 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011045 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011046
11047 boolean doNext = false;
11048
11049 synchronized(this) {
11050 ReceiverList rl
11051 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
11052 if (rl != null) {
11053 if (rl.curBroadcast != null) {
11054 BroadcastRecord r = rl.curBroadcast;
11055 doNext = finishReceiverLocked(
11056 receiver.asBinder(), r.resultCode, r.resultData,
11057 r.resultExtras, r.resultAbort, true);
11058 }
11059
11060 if (rl.app != null) {
11061 rl.app.receivers.remove(rl);
11062 }
11063 removeReceiverLocked(rl);
11064 if (rl.linkedToDeath) {
11065 rl.linkedToDeath = false;
11066 rl.receiver.asBinder().unlinkToDeath(rl, 0);
11067 }
11068 }
11069 }
11070
11071 if (!doNext) {
11072 return;
11073 }
11074
11075 final long origId = Binder.clearCallingIdentity();
11076 processNextBroadcast(false);
11077 trimApplications();
11078 Binder.restoreCallingIdentity(origId);
11079 }
11080
11081 void removeReceiverLocked(ReceiverList rl) {
11082 mRegisteredReceivers.remove(rl.receiver.asBinder());
11083 int N = rl.size();
11084 for (int i=0; i<N; i++) {
11085 mReceiverResolver.removeFilter(rl.get(i));
11086 }
11087 }
11088
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070011089 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
11090 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
11091 ProcessRecord r = mLruProcesses.get(i);
11092 if (r.thread != null) {
11093 try {
11094 r.thread.dispatchPackageBroadcast(cmd, packages);
11095 } catch (RemoteException ex) {
11096 }
11097 }
11098 }
11099 }
11100
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011101 private final int broadcastIntentLocked(ProcessRecord callerApp,
11102 String callerPackage, Intent intent, String resolvedType,
11103 IIntentReceiver resultTo, int resultCode, String resultData,
11104 Bundle map, String requiredPermission,
11105 boolean ordered, boolean sticky, int callingPid, int callingUid) {
11106 intent = new Intent(intent);
11107
Dianne Hackborne7f97212011-02-24 14:40:20 -080011108 // By default broadcasts do not go to stopped apps.
11109 intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
11110
Joe Onorato8a9b2202010-02-26 18:56:32 -080011111 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011112 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
11113 + " ordered=" + ordered);
11114 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011115 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011116 }
11117
11118 // Handle special intents: if this broadcast is from the package
11119 // manager about a package being removed, we need to remove all of
11120 // its activities from the history stack.
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011121 final boolean uidRemoved = Intent.ACTION_UID_REMOVED.equals(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011122 intent.getAction());
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011123 if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
11124 || Intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080011125 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011126 || uidRemoved) {
11127 if (checkComponentPermission(
11128 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011129 callingPid, callingUid, -1, true)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011130 == PackageManager.PERMISSION_GRANTED) {
11131 if (uidRemoved) {
11132 final Bundle intentExtras = intent.getExtras();
11133 final int uid = intentExtras != null
11134 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
11135 if (uid >= 0) {
11136 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
11137 synchronized (bs) {
11138 bs.removeUidStatsLocked(uid);
11139 }
11140 }
11141 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011142 // If resources are unvailble just force stop all
11143 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080011144 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011145 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
11146 if (list != null && (list.length > 0)) {
11147 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011148 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011149 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070011150 sendPackageBroadcastLocked(
11151 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011152 }
11153 } else {
11154 Uri data = intent.getData();
11155 String ssp;
11156 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
11157 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
11158 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011159 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070011160 }
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011161 if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070011162 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
11163 new String[] {ssp});
11164 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011165 }
11166 }
11167 }
11168 } else {
11169 String msg = "Permission Denial: " + intent.getAction()
11170 + " broadcast from " + callerPackage + " (pid=" + callingPid
11171 + ", uid=" + callingUid + ")"
11172 + " requires "
11173 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011174 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011175 throw new SecurityException(msg);
11176 }
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011177
11178 // Special case for adding a package: by default turn on compatibility
11179 // mode.
11180 } else if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())) {
Dianne Hackborn8ea5e1d2011-05-27 16:45:31 -070011181 Uri data = intent.getData();
11182 String ssp;
11183 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
11184 mCompatModePackages.handlePackageAddedLocked(ssp,
11185 intent.getBooleanExtra(Intent.EXTRA_REPLACING, false));
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011186 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011187 }
11188
11189 /*
11190 * If this is the time zone changed action, queue up a message that will reset the timezone
11191 * of all currently running processes. This message will get queued up before the broadcast
11192 * happens.
11193 */
11194 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
11195 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
11196 }
11197
Robert Greenwalt03595d02010-11-02 14:08:23 -070011198 if (intent.ACTION_CLEAR_DNS_CACHE.equals(intent.getAction())) {
11199 mHandler.sendEmptyMessage(CLEAR_DNS_CACHE);
11200 }
11201
Robert Greenwalt434203a2010-10-11 16:00:27 -070011202 if (Proxy.PROXY_CHANGE_ACTION.equals(intent.getAction())) {
11203 ProxyProperties proxy = intent.getParcelableExtra("proxy");
11204 mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY, proxy));
11205 }
11206
Dianne Hackborn854060af2009-07-09 18:14:31 -070011207 /*
11208 * Prevent non-system code (defined here to be non-persistent
11209 * processes) from sending protected broadcasts.
11210 */
11211 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
11212 || callingUid == Process.SHELL_UID || callingUid == 0) {
11213 // Always okay.
11214 } else if (callerApp == null || !callerApp.persistent) {
11215 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011216 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -070011217 intent.getAction())) {
11218 String msg = "Permission Denial: not allowed to send broadcast "
11219 + intent.getAction() + " from pid="
11220 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011221 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070011222 throw new SecurityException(msg);
11223 }
11224 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011225 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070011226 return BROADCAST_SUCCESS;
11227 }
11228 }
11229
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011230 // Add to the sticky list if requested.
11231 if (sticky) {
11232 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
11233 callingPid, callingUid)
11234 != PackageManager.PERMISSION_GRANTED) {
11235 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
11236 + callingPid + ", uid=" + callingUid
11237 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011238 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011239 throw new SecurityException(msg);
11240 }
11241 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011242 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011243 + " and enforce permission " + requiredPermission);
11244 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
11245 }
11246 if (intent.getComponent() != null) {
11247 throw new SecurityException(
11248 "Sticky broadcasts can't target a specific component");
11249 }
11250 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
11251 if (list == null) {
11252 list = new ArrayList<Intent>();
11253 mStickyBroadcasts.put(intent.getAction(), list);
11254 }
11255 int N = list.size();
11256 int i;
11257 for (i=0; i<N; i++) {
11258 if (intent.filterEquals(list.get(i))) {
11259 // This sticky already exists, replace it.
11260 list.set(i, new Intent(intent));
11261 break;
11262 }
11263 }
11264 if (i >= N) {
11265 list.add(new Intent(intent));
11266 }
11267 }
11268
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011269 // Figure out who all will receive this broadcast.
11270 List receivers = null;
11271 List<BroadcastFilter> registeredReceivers = null;
11272 try {
11273 if (intent.getComponent() != null) {
11274 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011275 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070011276 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011277 if (ai != null) {
11278 receivers = new ArrayList();
11279 ResolveInfo ri = new ResolveInfo();
11280 ri.activityInfo = ai;
11281 receivers.add(ri);
11282 }
11283 } else {
11284 // Need to resolve the intent to interested receivers...
11285 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
11286 == 0) {
11287 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011288 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011289 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011290 }
Mihai Preda074edef2009-05-18 17:13:31 +020011291 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011292 }
11293 } catch (RemoteException ex) {
11294 // pm is in same process, this will never happen.
11295 }
11296
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011297 final boolean replacePending =
11298 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
11299
Joe Onorato8a9b2202010-02-26 18:56:32 -080011300 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011301 + " replacePending=" + replacePending);
11302
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011303 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
11304 if (!ordered && NR > 0) {
11305 // If we are not serializing this broadcast, then send the
11306 // registered receivers separately so they don't wait for the
11307 // components to be launched.
11308 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
11309 callerPackage, callingPid, callingUid, requiredPermission,
11310 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011311 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011312 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011313 TAG, "Enqueueing parallel broadcast " + r
11314 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011315 boolean replaced = false;
11316 if (replacePending) {
11317 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
11318 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011319 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011320 "***** DROPPING PARALLEL: " + intent);
11321 mParallelBroadcasts.set(i, r);
11322 replaced = true;
11323 break;
11324 }
11325 }
11326 }
11327 if (!replaced) {
11328 mParallelBroadcasts.add(r);
11329 scheduleBroadcastsLocked();
11330 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011331 registeredReceivers = null;
11332 NR = 0;
11333 }
11334
11335 // Merge into one list.
11336 int ir = 0;
11337 if (receivers != null) {
11338 // A special case for PACKAGE_ADDED: do not allow the package
11339 // being added to see this broadcast. This prevents them from
11340 // using this as a back door to get run as soon as they are
11341 // installed. Maybe in the future we want to have a special install
11342 // broadcast or such for apps, but we'd like to deliberately make
11343 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011344 String skipPackages[] = null;
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011345 if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
11346 || Intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
11347 || Intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011348 Uri data = intent.getData();
11349 if (data != null) {
11350 String pkgName = data.getSchemeSpecificPart();
11351 if (pkgName != null) {
11352 skipPackages = new String[] { pkgName };
11353 }
11354 }
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011355 } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011356 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070011357 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011358 if (skipPackages != null && (skipPackages.length > 0)) {
11359 for (String skipPackage : skipPackages) {
11360 if (skipPackage != null) {
11361 int NT = receivers.size();
11362 for (int it=0; it<NT; it++) {
11363 ResolveInfo curt = (ResolveInfo)receivers.get(it);
11364 if (curt.activityInfo.packageName.equals(skipPackage)) {
11365 receivers.remove(it);
11366 it--;
11367 NT--;
11368 }
11369 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011370 }
11371 }
11372 }
11373
11374 int NT = receivers != null ? receivers.size() : 0;
11375 int it = 0;
11376 ResolveInfo curt = null;
11377 BroadcastFilter curr = null;
11378 while (it < NT && ir < NR) {
11379 if (curt == null) {
11380 curt = (ResolveInfo)receivers.get(it);
11381 }
11382 if (curr == null) {
11383 curr = registeredReceivers.get(ir);
11384 }
11385 if (curr.getPriority() >= curt.priority) {
11386 // Insert this broadcast record into the final list.
11387 receivers.add(it, curr);
11388 ir++;
11389 curr = null;
11390 it++;
11391 NT++;
11392 } else {
11393 // Skip to the next ResolveInfo in the final list.
11394 it++;
11395 curt = null;
11396 }
11397 }
11398 }
11399 while (ir < NR) {
11400 if (receivers == null) {
11401 receivers = new ArrayList();
11402 }
11403 receivers.add(registeredReceivers.get(ir));
11404 ir++;
11405 }
11406
11407 if ((receivers != null && receivers.size() > 0)
11408 || resultTo != null) {
11409 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
11410 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011411 receivers, resultTo, resultCode, resultData, map, ordered,
11412 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011413 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011414 TAG, "Enqueueing ordered broadcast " + r
11415 + ": prev had " + mOrderedBroadcasts.size());
11416 if (DEBUG_BROADCAST) {
11417 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011418 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011419 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011420 boolean replaced = false;
11421 if (replacePending) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011422 for (int i=mOrderedBroadcasts.size()-1; i>0; i--) {
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011423 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011424 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011425 "***** DROPPING ORDERED: " + intent);
11426 mOrderedBroadcasts.set(i, r);
11427 replaced = true;
11428 break;
11429 }
11430 }
11431 }
11432 if (!replaced) {
11433 mOrderedBroadcasts.add(r);
11434 scheduleBroadcastsLocked();
11435 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011436 }
11437
11438 return BROADCAST_SUCCESS;
11439 }
11440
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011441 final Intent verifyBroadcastLocked(Intent intent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011442 // Refuse possible leaked file descriptors
11443 if (intent != null && intent.hasFileDescriptors() == true) {
11444 throw new IllegalArgumentException("File descriptors passed in Intent");
11445 }
11446
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011447 int flags = intent.getFlags();
11448
11449 if (!mProcessesReady) {
11450 // if the caller really truly claims to know what they're doing, go
11451 // ahead and allow the broadcast without launching any receivers
11452 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
11453 intent = new Intent(intent);
11454 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
11455 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
11456 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
11457 + " before boot completion");
11458 throw new IllegalStateException("Cannot broadcast before boot completed");
11459 }
11460 }
11461
11462 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
11463 throw new IllegalArgumentException(
11464 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
11465 }
11466
11467 return intent;
11468 }
11469
11470 public final int broadcastIntent(IApplicationThread caller,
11471 Intent intent, String resolvedType, IIntentReceiver resultTo,
11472 int resultCode, String resultData, Bundle map,
11473 String requiredPermission, boolean serialized, boolean sticky) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011474 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011475 intent = verifyBroadcastLocked(intent);
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011476
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011477 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11478 final int callingPid = Binder.getCallingPid();
11479 final int callingUid = Binder.getCallingUid();
11480 final long origId = Binder.clearCallingIdentity();
11481 int res = broadcastIntentLocked(callerApp,
11482 callerApp != null ? callerApp.info.packageName : null,
11483 intent, resolvedType, resultTo,
11484 resultCode, resultData, map, requiredPermission, serialized,
11485 sticky, callingPid, callingUid);
11486 Binder.restoreCallingIdentity(origId);
11487 return res;
11488 }
11489 }
11490
11491 int broadcastIntentInPackage(String packageName, int uid,
11492 Intent intent, String resolvedType, IIntentReceiver resultTo,
11493 int resultCode, String resultData, Bundle map,
11494 String requiredPermission, boolean serialized, boolean sticky) {
11495 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011496 intent = verifyBroadcastLocked(intent);
11497
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011498 final long origId = Binder.clearCallingIdentity();
11499 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
11500 resultTo, resultCode, resultData, map, requiredPermission,
11501 serialized, sticky, -1, uid);
11502 Binder.restoreCallingIdentity(origId);
11503 return res;
11504 }
11505 }
11506
11507 public final void unbroadcastIntent(IApplicationThread caller,
11508 Intent intent) {
11509 // Refuse possible leaked file descriptors
11510 if (intent != null && intent.hasFileDescriptors() == true) {
11511 throw new IllegalArgumentException("File descriptors passed in Intent");
11512 }
11513
11514 synchronized(this) {
11515 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
11516 != PackageManager.PERMISSION_GRANTED) {
11517 String msg = "Permission Denial: unbroadcastIntent() from pid="
11518 + Binder.getCallingPid()
11519 + ", uid=" + Binder.getCallingUid()
11520 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011521 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011522 throw new SecurityException(msg);
11523 }
11524 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
11525 if (list != null) {
11526 int N = list.size();
11527 int i;
11528 for (i=0; i<N; i++) {
11529 if (intent.filterEquals(list.get(i))) {
11530 list.remove(i);
11531 break;
11532 }
11533 }
11534 }
11535 }
11536 }
11537
11538 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
11539 String resultData, Bundle resultExtras, boolean resultAbort,
11540 boolean explicit) {
11541 if (mOrderedBroadcasts.size() == 0) {
11542 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011543 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011544 }
11545 return false;
11546 }
11547 BroadcastRecord r = mOrderedBroadcasts.get(0);
11548 if (r.receiver == null) {
11549 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011550 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011551 }
11552 return false;
11553 }
11554 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011555 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011556 return false;
11557 }
11558 int state = r.state;
11559 r.state = r.IDLE;
11560 if (state == r.IDLE) {
11561 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011562 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011563 }
11564 }
11565 r.receiver = null;
11566 r.intent.setComponent(null);
11567 if (r.curApp != null) {
11568 r.curApp.curReceiver = null;
11569 }
11570 if (r.curFilter != null) {
11571 r.curFilter.receiverList.curBroadcast = null;
11572 }
11573 r.curFilter = null;
11574 r.curApp = null;
11575 r.curComponent = null;
11576 r.curReceiver = null;
11577 mPendingBroadcast = null;
11578
11579 r.resultCode = resultCode;
11580 r.resultData = resultData;
11581 r.resultExtras = resultExtras;
11582 r.resultAbort = resultAbort;
11583
11584 // We will process the next receiver right now if this is finishing
11585 // an app receiver (which is always asynchronous) or after we have
11586 // come back from calling a receiver.
11587 return state == BroadcastRecord.APP_RECEIVE
11588 || state == BroadcastRecord.CALL_DONE_RECEIVE;
11589 }
11590
11591 public void finishReceiver(IBinder who, int resultCode, String resultData,
11592 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011593 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011594
11595 // Refuse possible leaked file descriptors
11596 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
11597 throw new IllegalArgumentException("File descriptors passed in Bundle");
11598 }
11599
11600 boolean doNext;
11601
11602 final long origId = Binder.clearCallingIdentity();
11603
11604 synchronized(this) {
11605 doNext = finishReceiverLocked(
11606 who, resultCode, resultData, resultExtras, resultAbort, true);
11607 }
11608
11609 if (doNext) {
11610 processNextBroadcast(false);
11611 }
11612 trimApplications();
11613
11614 Binder.restoreCallingIdentity(origId);
11615 }
11616
Jeff Brown4d94a762010-09-23 11:33:28 -070011617 private final void logBroadcastReceiverDiscardLocked(BroadcastRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011618 if (r.nextReceiver > 0) {
11619 Object curReceiver = r.receivers.get(r.nextReceiver-1);
11620 if (curReceiver instanceof BroadcastFilter) {
11621 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080011622 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011623 System.identityHashCode(r),
11624 r.intent.getAction(),
11625 r.nextReceiver - 1,
11626 System.identityHashCode(bf));
11627 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080011628 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011629 System.identityHashCode(r),
11630 r.intent.getAction(),
11631 r.nextReceiver - 1,
11632 ((ResolveInfo)curReceiver).toString());
11633 }
11634 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011635 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011636 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011637 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011638 System.identityHashCode(r),
11639 r.intent.getAction(),
11640 r.nextReceiver,
11641 "NONE");
11642 }
11643 }
11644
Jeff Brown4d94a762010-09-23 11:33:28 -070011645 private final void setBroadcastTimeoutLocked(long timeoutTime) {
11646 if (! mPendingBroadcastTimeoutMessage) {
11647 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
11648 mHandler.sendMessageAtTime(msg, timeoutTime);
11649 mPendingBroadcastTimeoutMessage = true;
11650 }
11651 }
11652
11653 private final void cancelBroadcastTimeoutLocked() {
11654 if (mPendingBroadcastTimeoutMessage) {
11655 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
11656 mPendingBroadcastTimeoutMessage = false;
11657 }
11658 }
11659
11660 private final void broadcastTimeoutLocked(boolean fromMsg) {
11661 if (fromMsg) {
11662 mPendingBroadcastTimeoutMessage = false;
11663 }
11664
11665 if (mOrderedBroadcasts.size() == 0) {
11666 return;
11667 }
11668
11669 long now = SystemClock.uptimeMillis();
11670 BroadcastRecord r = mOrderedBroadcasts.get(0);
11671 if (fromMsg) {
11672 if (mDidDexOpt) {
11673 // Delay timeouts until dexopt finishes.
11674 mDidDexOpt = false;
11675 long timeoutTime = SystemClock.uptimeMillis() + BROADCAST_TIMEOUT;
11676 setBroadcastTimeoutLocked(timeoutTime);
11677 return;
11678 }
11679 if (! mProcessesReady) {
11680 // Only process broadcast timeouts if the system is ready. That way
11681 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
11682 // to do heavy lifting for system up.
11683 return;
11684 }
11685
11686 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
11687 if (timeoutTime > now) {
11688 // We can observe premature timeouts because we do not cancel and reset the
11689 // broadcast timeout message after each receiver finishes. Instead, we set up
11690 // an initial timeout then kick it down the road a little further as needed
11691 // when it expires.
11692 if (DEBUG_BROADCAST) Slog.v(TAG,
11693 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
11694 + timeoutTime);
11695 setBroadcastTimeoutLocked(timeoutTime);
11696 return;
11697 }
11698 }
11699
11700 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver
11701 + ", started " + (now - r.receiverTime) + "ms ago");
11702 r.receiverTime = now;
11703 r.anrCount++;
11704
11705 // Current receiver has passed its expiration date.
11706 if (r.nextReceiver <= 0) {
11707 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
11708 return;
11709 }
11710
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011711 ProcessRecord app = null;
11712 String anrMessage = null;
11713
Jeff Brown4d94a762010-09-23 11:33:28 -070011714 Object curReceiver = r.receivers.get(r.nextReceiver-1);
11715 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
11716 logBroadcastReceiverDiscardLocked(r);
11717 if (curReceiver instanceof BroadcastFilter) {
11718 BroadcastFilter bf = (BroadcastFilter)curReceiver;
11719 if (bf.receiverList.pid != 0
11720 && bf.receiverList.pid != MY_PID) {
11721 synchronized (this.mPidsSelfLocked) {
11722 app = this.mPidsSelfLocked.get(
11723 bf.receiverList.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011724 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011725 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011726 } else {
11727 app = r.curApp;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011728 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011729
Jeff Brown4d94a762010-09-23 11:33:28 -070011730 if (app != null) {
11731 anrMessage = "Broadcast of " + r.intent.toString();
11732 }
11733
11734 if (mPendingBroadcast == r) {
11735 mPendingBroadcast = null;
11736 }
11737
11738 // Move on to the next receiver.
11739 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
11740 r.resultExtras, r.resultAbort, true);
11741 scheduleBroadcastsLocked();
11742
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011743 if (anrMessage != null) {
Jeff Brown4d94a762010-09-23 11:33:28 -070011744 // Post the ANR to the handler since we do not want to process ANRs while
11745 // potentially holding our lock.
11746 mHandler.post(new AppNotResponding(app, anrMessage));
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011747 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011748 }
11749
11750 private final void processCurBroadcastLocked(BroadcastRecord r,
11751 ProcessRecord app) throws RemoteException {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011752 if (DEBUG_BROADCAST) Slog.v(TAG,
11753 "Process cur broadcast " + r + " for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011754 if (app.thread == null) {
11755 throw new RemoteException();
11756 }
11757 r.receiver = app.thread.asBinder();
11758 r.curApp = app;
11759 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011760 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011761
11762 // Tell the application to launch this receiver.
11763 r.intent.setComponent(r.curComponent);
11764
11765 boolean started = false;
11766 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011767 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011768 "Delivering to component " + r.curComponent
11769 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070011770 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011771 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
Dianne Hackborne2515ee2011-04-27 18:52:56 -040011772 compatibilityInfoForPackageLocked(r.curReceiver.applicationInfo),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011773 r.resultCode, r.resultData, r.resultExtras, r.ordered);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011774 if (DEBUG_BROADCAST) Slog.v(TAG,
11775 "Process cur broadcast " + r + " DELIVERED for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011776 started = true;
11777 } finally {
11778 if (!started) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011779 if (DEBUG_BROADCAST) Slog.v(TAG,
11780 "Process cur broadcast " + r + ": NOT STARTED!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011781 r.receiver = null;
11782 r.curApp = null;
11783 app.curReceiver = null;
11784 }
11785 }
11786
11787 }
11788
Jeff Brown4d94a762010-09-23 11:33:28 -070011789 static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011790 Intent intent, int resultCode, String data, Bundle extras,
11791 boolean ordered, boolean sticky) throws RemoteException {
Jeff Brown4d94a762010-09-23 11:33:28 -070011792 // Send the intent to the receiver asynchronously using one-way binder calls.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011793 if (app != null && app.thread != null) {
11794 // If we have an app thread, do the call through that so it is
11795 // correctly ordered with other one-way calls.
11796 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011797 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011798 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011799 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011800 }
11801 }
11802
Jeff Brown4d94a762010-09-23 11:33:28 -070011803 private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011804 BroadcastFilter filter, boolean ordered) {
11805 boolean skip = false;
11806 if (filter.requiredPermission != null) {
11807 int perm = checkComponentPermission(filter.requiredPermission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011808 r.callingPid, r.callingUid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011809 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011810 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011811 + r.intent.toString()
11812 + " from " + r.callerPackage + " (pid="
11813 + r.callingPid + ", uid=" + r.callingUid + ")"
11814 + " requires " + filter.requiredPermission
11815 + " due to registered receiver " + filter);
11816 skip = true;
11817 }
11818 }
11819 if (r.requiredPermission != null) {
11820 int perm = checkComponentPermission(r.requiredPermission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011821 filter.receiverList.pid, filter.receiverList.uid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011822 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011823 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011824 + r.intent.toString()
11825 + " to " + filter.receiverList.app
11826 + " (pid=" + filter.receiverList.pid
11827 + ", uid=" + filter.receiverList.uid + ")"
11828 + " requires " + r.requiredPermission
11829 + " due to sender " + r.callerPackage
11830 + " (uid " + r.callingUid + ")");
11831 skip = true;
11832 }
11833 }
11834
11835 if (!skip) {
11836 // If this is not being sent as an ordered broadcast, then we
11837 // don't want to touch the fields that keep track of the current
11838 // state of ordered broadcasts.
11839 if (ordered) {
11840 r.receiver = filter.receiverList.receiver.asBinder();
11841 r.curFilter = filter;
11842 filter.receiverList.curBroadcast = r;
11843 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011844 if (filter.receiverList.app != null) {
11845 // Bump hosting application to no longer be in background
11846 // scheduling class. Note that we can't do that if there
11847 // isn't an app... but we can only be in that case for
11848 // things that directly call the IActivityManager API, which
11849 // are already core system stuff so don't matter for this.
11850 r.curApp = filter.receiverList.app;
11851 filter.receiverList.app.curReceiver = r;
11852 updateOomAdjLocked();
11853 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011854 }
11855 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011856 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011857 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011858 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011859 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011860 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011861 performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011862 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011863 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011864 if (ordered) {
11865 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
11866 }
11867 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011868 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011869 if (ordered) {
11870 r.receiver = null;
11871 r.curFilter = null;
11872 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011873 if (filter.receiverList.app != null) {
11874 filter.receiverList.app.curReceiver = null;
11875 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011876 }
11877 }
11878 }
11879 }
11880
Dianne Hackborn12527f92009-11-11 17:39:50 -080011881 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
11882 if (r.callingUid < 0) {
11883 // This was from a registerReceiver() call; ignore it.
11884 return;
11885 }
11886 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
11887 MAX_BROADCAST_HISTORY-1);
11888 r.finishTime = SystemClock.uptimeMillis();
11889 mBroadcastHistory[0] = r;
11890 }
11891
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011892 private final void processNextBroadcast(boolean fromMsg) {
11893 synchronized(this) {
11894 BroadcastRecord r;
11895
Joe Onorato8a9b2202010-02-26 18:56:32 -080011896 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011897 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011898 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011899
11900 updateCpuStats();
11901
11902 if (fromMsg) {
11903 mBroadcastsScheduled = false;
11904 }
11905
11906 // First, deliver any non-serialized broadcasts right away.
11907 while (mParallelBroadcasts.size() > 0) {
11908 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080011909 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011910 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011911 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011912 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011913 for (int i=0; i<N; i++) {
11914 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011915 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011916 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011917 + target + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011918 deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011919 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080011920 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011921 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011922 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011923 }
11924
11925 // Now take care of the next serialized one...
11926
11927 // If we are waiting for a process to come up to handle the next
11928 // broadcast, then do nothing at this point. Just in case, we
11929 // check that the process we're waiting for still exists.
11930 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070011931 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011932 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070011933 + mPendingBroadcast.curApp);
11934 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011935
11936 boolean isDead;
11937 synchronized (mPidsSelfLocked) {
11938 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
11939 }
11940 if (!isDead) {
11941 // It's still alive, so keep waiting
11942 return;
11943 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011944 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011945 + " died before responding to broadcast");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011946 mPendingBroadcast.state = BroadcastRecord.IDLE;
11947 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011948 mPendingBroadcast = null;
11949 }
11950 }
11951
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011952 boolean looped = false;
11953
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011954 do {
11955 if (mOrderedBroadcasts.size() == 0) {
11956 // No more broadcasts pending, so all done!
11957 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011958 if (looped) {
11959 // If we had finished the last ordered broadcast, then
11960 // make sure all processes have correct oom and sched
11961 // adjustments.
11962 updateOomAdjLocked();
11963 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011964 return;
11965 }
11966 r = mOrderedBroadcasts.get(0);
11967 boolean forceReceive = false;
11968
11969 // Ensure that even if something goes awry with the timeout
11970 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011971 // and continue to make progress.
11972 //
11973 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
Jeff Brown4d94a762010-09-23 11:33:28 -070011974 // receivers don't get executed with timeouts. They're intended for
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011975 // one time heavy lifting after system upgrades and can take
11976 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011977 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011978 if (mProcessesReady && r.dispatchTime > 0) {
Jeff Hamiltonacf84742010-05-25 22:10:18 -050011979 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011980 if ((numReceivers > 0) &&
11981 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011982 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011983 + " now=" + now
11984 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080011985 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011986 + " intent=" + r.intent
11987 + " numReceivers=" + numReceivers
11988 + " nextReceiver=" + r.nextReceiver
11989 + " state=" + r.state);
Jeff Brown4d94a762010-09-23 11:33:28 -070011990 broadcastTimeoutLocked(false); // forcibly finish this broadcast
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011991 forceReceive = true;
11992 r.state = BroadcastRecord.IDLE;
11993 }
11994 }
11995
11996 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011997 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011998 "processNextBroadcast() called when not idle (state="
11999 + r.state + ")");
12000 return;
12001 }
12002
12003 if (r.receivers == null || r.nextReceiver >= numReceivers
12004 || r.resultAbort || forceReceive) {
12005 // No more receivers for this broadcast! Send the final
12006 // result if requested...
12007 if (r.resultTo != null) {
12008 try {
12009 if (DEBUG_BROADCAST) {
12010 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012011 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012012 + " seq=" + seq + " app=" + r.callerApp);
12013 }
Jeff Brown4d94a762010-09-23 11:33:28 -070012014 performReceiveLocked(r.callerApp, r.resultTo,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012015 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012016 r.resultData, r.resultExtras, false, false);
Johannes Carlssonb5a86542010-10-27 10:08:10 +020012017 // Set this to null so that the reference
12018 // (local and remote) isnt kept in the mBroadcastHistory.
12019 r.resultTo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012020 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012021 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012022 }
12023 }
12024
Joe Onorato8a9b2202010-02-26 18:56:32 -080012025 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
Jeff Brown4d94a762010-09-23 11:33:28 -070012026 cancelBroadcastTimeoutLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012027
Joe Onorato8a9b2202010-02-26 18:56:32 -080012028 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012029 + r);
12030
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012031 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080012032 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012033 mOrderedBroadcasts.remove(0);
12034 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012035 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012036 continue;
12037 }
12038 } while (r == null);
12039
12040 // Get the next receiver...
12041 int recIdx = r.nextReceiver++;
12042
12043 // Keep track of when this receiver started, and make sure there
12044 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080012045 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012046 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080012047 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012048
Joe Onorato8a9b2202010-02-26 18:56:32 -080012049 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012050 + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070012051 }
12052 if (! mPendingBroadcastTimeoutMessage) {
12053 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012054 if (DEBUG_BROADCAST) Slog.v(TAG,
Jeff Brown4d94a762010-09-23 11:33:28 -070012055 "Submitting BROADCAST_TIMEOUT_MSG for " + r + " at " + timeoutTime);
12056 setBroadcastTimeoutLocked(timeoutTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012057 }
12058
12059 Object nextReceiver = r.receivers.get(recIdx);
12060 if (nextReceiver instanceof BroadcastFilter) {
12061 // Simple case: this is a registered receiver who gets
12062 // a direct call.
12063 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012064 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070012065 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012066 + filter + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070012067 deliverToRegisteredReceiverLocked(r, filter, r.ordered);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012068 if (r.receiver == null || !r.ordered) {
12069 // The receiver has already finished, so schedule to
12070 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070012071 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
12072 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012073 r.state = BroadcastRecord.IDLE;
12074 scheduleBroadcastsLocked();
12075 }
12076 return;
12077 }
12078
12079 // Hard case: need to instantiate the receiver, possibly
12080 // starting its application process to host it.
12081
12082 ResolveInfo info =
12083 (ResolveInfo)nextReceiver;
12084
12085 boolean skip = false;
12086 int perm = checkComponentPermission(info.activityInfo.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080012087 r.callingPid, r.callingUid, info.activityInfo.applicationInfo.uid,
12088 info.activityInfo.exported);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012089 if (perm != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080012090 if (!info.activityInfo.exported) {
12091 Slog.w(TAG, "Permission Denial: broadcasting "
12092 + r.intent.toString()
12093 + " from " + r.callerPackage + " (pid=" + r.callingPid
12094 + ", uid=" + r.callingUid + ")"
12095 + " is not exported from uid " + info.activityInfo.applicationInfo.uid
12096 + " due to receiver " + info.activityInfo.packageName
12097 + "/" + info.activityInfo.name);
12098 } else {
12099 Slog.w(TAG, "Permission Denial: broadcasting "
12100 + r.intent.toString()
12101 + " from " + r.callerPackage + " (pid=" + r.callingPid
12102 + ", uid=" + r.callingUid + ")"
12103 + " requires " + info.activityInfo.permission
12104 + " due to receiver " + info.activityInfo.packageName
12105 + "/" + info.activityInfo.name);
12106 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012107 skip = true;
12108 }
12109 if (r.callingUid != Process.SYSTEM_UID &&
12110 r.requiredPermission != null) {
12111 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012112 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012113 checkPermission(r.requiredPermission,
12114 info.activityInfo.applicationInfo.packageName);
12115 } catch (RemoteException e) {
12116 perm = PackageManager.PERMISSION_DENIED;
12117 }
12118 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012119 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012120 + r.intent + " to "
12121 + info.activityInfo.applicationInfo.packageName
12122 + " requires " + r.requiredPermission
12123 + " due to sender " + r.callerPackage
12124 + " (uid " + r.callingUid + ")");
12125 skip = true;
12126 }
12127 }
12128 if (r.curApp != null && r.curApp.crashing) {
12129 // If the target process is crashing, just skip it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012130 if (DEBUG_BROADCAST) Slog.v(TAG,
12131 "Skipping deliver ordered " + r + " to " + r.curApp
12132 + ": process crashing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012133 skip = true;
12134 }
12135
12136 if (skip) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012137 if (DEBUG_BROADCAST) Slog.v(TAG,
12138 "Skipping delivery of ordered " + r + " for whatever reason");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012139 r.receiver = null;
12140 r.curFilter = null;
12141 r.state = BroadcastRecord.IDLE;
12142 scheduleBroadcastsLocked();
12143 return;
12144 }
12145
12146 r.state = BroadcastRecord.APP_RECEIVE;
12147 String targetProcess = info.activityInfo.processName;
12148 r.curComponent = new ComponentName(
12149 info.activityInfo.applicationInfo.packageName,
12150 info.activityInfo.name);
12151 r.curReceiver = info.activityInfo;
12152
Dianne Hackborne7f97212011-02-24 14:40:20 -080012153 // Broadcast is being executed, its package can't be stopped.
12154 try {
12155 AppGlobals.getPackageManager().setPackageStoppedState(
12156 r.curComponent.getPackageName(), false);
12157 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -080012158 } catch (IllegalArgumentException e) {
12159 Slog.w(TAG, "Failed trying to unstop package "
12160 + r.curComponent.getPackageName() + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -080012161 }
12162
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012163 // Is this receiver's application already running?
12164 ProcessRecord app = getProcessRecordLocked(targetProcess,
12165 info.activityInfo.applicationInfo.uid);
12166 if (app != null && app.thread != null) {
12167 try {
Dianne Hackborn6c418d52011-06-29 14:05:33 -070012168 app.addPackage(info.activityInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012169 processCurBroadcastLocked(r, app);
12170 return;
12171 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012172 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012173 + r.curComponent, e);
12174 }
12175
12176 // If a dead object exception was thrown -- fall through to
12177 // restart the application.
12178 }
12179
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012180 // Not running -- get it started, to be executed when the app comes up.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012181 if (DEBUG_BROADCAST) Slog.v(TAG,
12182 "Need to start app " + targetProcess + " for broadcast " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012183 if ((r.curApp=startProcessLocked(targetProcess,
12184 info.activityInfo.applicationInfo, true,
12185 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012186 "broadcast", r.curComponent,
12187 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
12188 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012189 // Ah, this recipient is unavailable. Finish it if necessary,
12190 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012191 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012192 + info.activityInfo.applicationInfo.packageName + "/"
12193 + info.activityInfo.applicationInfo.uid + " for broadcast "
12194 + r.intent + ": process is bad");
Jeff Brown4d94a762010-09-23 11:33:28 -070012195 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012196 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
12197 r.resultExtras, r.resultAbort, true);
12198 scheduleBroadcastsLocked();
12199 r.state = BroadcastRecord.IDLE;
12200 return;
12201 }
12202
12203 mPendingBroadcast = r;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012204 mPendingBroadcastRecvIndex = recIdx;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012205 }
12206 }
12207
12208 // =========================================================
12209 // INSTRUMENTATION
12210 // =========================================================
12211
12212 public boolean startInstrumentation(ComponentName className,
12213 String profileFile, int flags, Bundle arguments,
12214 IInstrumentationWatcher watcher) {
12215 // Refuse possible leaked file descriptors
12216 if (arguments != null && arguments.hasFileDescriptors()) {
12217 throw new IllegalArgumentException("File descriptors passed in Bundle");
12218 }
12219
12220 synchronized(this) {
12221 InstrumentationInfo ii = null;
12222 ApplicationInfo ai = null;
12223 try {
12224 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012225 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012226 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012227 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012228 } catch (PackageManager.NameNotFoundException e) {
12229 }
12230 if (ii == null) {
12231 reportStartInstrumentationFailure(watcher, className,
12232 "Unable to find instrumentation info for: " + className);
12233 return false;
12234 }
12235 if (ai == null) {
12236 reportStartInstrumentationFailure(watcher, className,
12237 "Unable to find instrumentation target package: " + ii.targetPackage);
12238 return false;
12239 }
12240
12241 int match = mContext.getPackageManager().checkSignatures(
12242 ii.targetPackage, ii.packageName);
12243 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
12244 String msg = "Permission Denial: starting instrumentation "
12245 + className + " from pid="
12246 + Binder.getCallingPid()
12247 + ", uid=" + Binder.getCallingPid()
12248 + " not allowed because package " + ii.packageName
12249 + " does not have a signature matching the target "
12250 + ii.targetPackage;
12251 reportStartInstrumentationFailure(watcher, className, msg);
12252 throw new SecurityException(msg);
12253 }
12254
12255 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012256 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012257 ProcessRecord app = addAppLocked(ai);
12258 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070012259 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012260 app.instrumentationProfileFile = profileFile;
12261 app.instrumentationArguments = arguments;
12262 app.instrumentationWatcher = watcher;
12263 app.instrumentationResultClass = className;
12264 Binder.restoreCallingIdentity(origId);
12265 }
12266
12267 return true;
12268 }
12269
12270 /**
12271 * Report errors that occur while attempting to start Instrumentation. Always writes the
12272 * error to the logs, but if somebody is watching, send the report there too. This enables
12273 * the "am" command to report errors with more information.
12274 *
12275 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
12276 * @param cn The component name of the instrumentation.
12277 * @param report The error report.
12278 */
12279 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
12280 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012281 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012282 try {
12283 if (watcher != null) {
12284 Bundle results = new Bundle();
12285 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
12286 results.putString("Error", report);
12287 watcher.instrumentationStatus(cn, -1, results);
12288 }
12289 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012290 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012291 }
12292 }
12293
12294 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
12295 if (app.instrumentationWatcher != null) {
12296 try {
12297 // NOTE: IInstrumentationWatcher *must* be oneway here
12298 app.instrumentationWatcher.instrumentationFinished(
12299 app.instrumentationClass,
12300 resultCode,
12301 results);
12302 } catch (RemoteException e) {
12303 }
12304 }
12305 app.instrumentationWatcher = null;
12306 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070012307 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012308 app.instrumentationProfileFile = null;
12309 app.instrumentationArguments = null;
12310
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012311 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012312 }
12313
12314 public void finishInstrumentation(IApplicationThread target,
12315 int resultCode, Bundle results) {
12316 // Refuse possible leaked file descriptors
12317 if (results != null && results.hasFileDescriptors()) {
12318 throw new IllegalArgumentException("File descriptors passed in Intent");
12319 }
12320
12321 synchronized(this) {
12322 ProcessRecord app = getRecordForAppLocked(target);
12323 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012324 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012325 return;
12326 }
12327 final long origId = Binder.clearCallingIdentity();
12328 finishInstrumentationLocked(app, resultCode, results);
12329 Binder.restoreCallingIdentity(origId);
12330 }
12331 }
12332
12333 // =========================================================
12334 // CONFIGURATION
12335 // =========================================================
12336
12337 public ConfigurationInfo getDeviceConfigurationInfo() {
12338 ConfigurationInfo config = new ConfigurationInfo();
12339 synchronized (this) {
12340 config.reqTouchScreen = mConfiguration.touchscreen;
12341 config.reqKeyboardType = mConfiguration.keyboard;
12342 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070012343 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
12344 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012345 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
12346 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070012347 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
12348 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012349 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
12350 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070012351 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012352 }
12353 return config;
12354 }
12355
12356 public Configuration getConfiguration() {
12357 Configuration ci;
12358 synchronized(this) {
12359 ci = new Configuration(mConfiguration);
12360 }
12361 return ci;
12362 }
12363
12364 public void updateConfiguration(Configuration values) {
12365 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
12366 "updateConfiguration()");
12367
12368 synchronized(this) {
12369 if (values == null && mWindowManager != null) {
12370 // sentinel: fetch the current configuration from the window manager
12371 values = mWindowManager.computeNewConfiguration();
12372 }
12373
12374 final long origId = Binder.clearCallingIdentity();
12375 updateConfigurationLocked(values, null);
12376 Binder.restoreCallingIdentity(origId);
12377 }
12378 }
12379
12380 /**
12381 * Do either or both things: (1) change the current configuration, and (2)
12382 * make sure the given activity is running with the (now) current
12383 * configuration. Returns true if the activity has been left running, or
12384 * false if <var>starting</var> is being destroyed to match the new
12385 * configuration.
12386 */
12387 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012388 ActivityRecord starting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012389 int changes = 0;
12390
12391 boolean kept = true;
12392
12393 if (values != null) {
12394 Configuration newConfig = new Configuration(mConfiguration);
12395 changes = newConfig.updateFrom(values);
12396 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070012397 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012398 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012399 }
12400
Doug Zongker2bec3d42009-12-04 12:52:44 -080012401 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012402
12403 if (values.locale != null) {
12404 saveLocaleLocked(values.locale,
12405 !values.locale.equals(mConfiguration.locale),
12406 values.userSetLocale);
12407 }
12408
Dianne Hackborne36d6e22010-02-17 19:46:25 -080012409 mConfigurationSeq++;
12410 if (mConfigurationSeq <= 0) {
12411 mConfigurationSeq = 1;
12412 }
12413 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012414 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012415 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080012416
12417 AttributeCache ac = AttributeCache.instance();
12418 if (ac != null) {
12419 ac.updateConfiguration(mConfiguration);
12420 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012421
Dianne Hackborn2f0b1752011-05-31 17:59:49 -070012422 // Make sure all resources in our process are updated
12423 // right now, so that anyone who is going to retrieve
12424 // resource values after we return will be sure to get
12425 // the new ones. This is especially important during
12426 // boot, where the first config change needs to guarantee
12427 // all resources have that config before following boot
12428 // code is executed.
12429 mSystemThread.applyConfigurationToResources(newConfig);
12430
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080012431 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
12432 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
12433 msg.obj = new Configuration(mConfiguration);
12434 mHandler.sendMessage(msg);
12435 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012436
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012437 for (int i=mLruProcesses.size()-1; i>=0; i--) {
12438 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012439 try {
12440 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012441 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070012442 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012443 app.thread.scheduleConfigurationChanged(mConfiguration);
12444 }
12445 } catch (Exception e) {
12446 }
12447 }
12448 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012449 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
12450 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012451 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
12452 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080012453 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
12454 broadcastIntentLocked(null, null,
12455 new Intent(Intent.ACTION_LOCALE_CHANGED),
12456 null, null, 0, null, null,
12457 null, false, false, MY_PID, Process.SYSTEM_UID);
12458 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012459 }
12460 }
12461
12462 if (changes != 0 && starting == null) {
12463 // If the configuration changed, and the caller is not already
12464 // in the process of starting an activity, then find the top
12465 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012466 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012467 }
12468
12469 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012470 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
Dianne Hackborn5f4d6432010-12-21 20:40:11 -080012471 // And we need to make sure at this point that all other activities
12472 // are made visible with the correct configuration.
12473 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012474 }
12475
Dianne Hackborne36d6e22010-02-17 19:46:25 -080012476 if (values != null && mWindowManager != null) {
12477 mWindowManager.setNewConfiguration(mConfiguration);
12478 }
12479
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012480 return kept;
12481 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012482
12483 /**
12484 * Save the locale. You must be inside a synchronized (this) block.
12485 */
12486 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
12487 if(isDiff) {
12488 SystemProperties.set("user.language", l.getLanguage());
12489 SystemProperties.set("user.region", l.getCountry());
12490 }
12491
12492 if(isPersist) {
12493 SystemProperties.set("persist.sys.language", l.getLanguage());
12494 SystemProperties.set("persist.sys.country", l.getCountry());
12495 SystemProperties.set("persist.sys.localevar", l.getVariant());
12496 }
12497 }
12498
12499 // =========================================================
12500 // LIFETIME MANAGEMENT
12501 // =========================================================
12502
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012503 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
12504 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012505 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012506 // This adjustment has already been computed. If we are calling
12507 // from the top, we may have already computed our adjustment with
12508 // an earlier hidden adjustment that isn't really for us... if
12509 // so, use the new hidden adjustment.
12510 if (!recursed && app.hidden) {
12511 app.curAdj = hiddenAdj;
12512 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012513 return app.curAdj;
12514 }
12515
12516 if (app.thread == null) {
12517 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012518 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012519 return (app.curAdj=EMPTY_APP_ADJ);
12520 }
12521
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012522 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
12523 // The max adjustment doesn't allow this app to be anything
12524 // below foreground, so it is not worth doing work for it.
12525 app.adjType = "fixed";
12526 app.adjSeq = mAdjSeq;
12527 app.curRawAdj = app.maxAdj;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012528 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012529 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
12530 return (app.curAdj=app.maxAdj);
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012531 }
12532
12533 final boolean hadForegroundActivities = app.foregroundActivities;
12534
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012535 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012536 app.adjSource = null;
12537 app.adjTarget = null;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012538 app.keeping = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012539 app.empty = false;
12540 app.hidden = false;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012541 app.foregroundActivities = false;
12542
12543 final int activitiesSize = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012544
The Android Open Source Project4df24232009-03-05 14:34:35 -080012545 // Determine the importance of the process, starting with most
12546 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012547 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012548 int schedGroup;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012549 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012550 // The last app on the list is the foreground app.
12551 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012552 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012553 app.adjType = "top-activity";
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012554 app.foregroundActivities = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012555 } else if (app.instrumentationClass != null) {
12556 // Don't want to kill running instrumentation.
12557 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012558 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012559 app.adjType = "instrumentation";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012560 } else if (app.curReceiver != null ||
12561 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
12562 // An app that is currently receiving a broadcast also
12563 // counts as being in the foreground.
12564 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012565 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012566 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012567 } else if (app.executingServices.size() > 0) {
12568 // An app that is currently executing a service callback also
12569 // counts as being in the foreground.
12570 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012571 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012572 app.adjType = "exec-service";
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012573 } else if (activitiesSize > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012574 // This app is in the background with paused activities.
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012575 // We inspect activities to potentially upgrade adjustment further below.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012576 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012577 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012578 app.hidden = true;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012579 app.adjType = "bg-activities";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012580 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012581 // A very not-needed process. If this is lower in the lru list,
12582 // we will push it in to the empty bucket.
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012583 adj = hiddenAdj;
12584 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012585 app.hidden = true;
12586 app.empty = true;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012587 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012588 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012589
12590 // Examine all activities if not already foreground.
12591 if (!app.foregroundActivities && activitiesSize > 0) {
12592 for (int j = 0; j < activitiesSize; j++) {
12593 final ActivityRecord r = app.activities.get(j);
12594 if (r.visible) {
12595 // App has a visible activity; only upgrade adjustment.
12596 if (adj > VISIBLE_APP_ADJ) {
12597 adj = VISIBLE_APP_ADJ;
12598 app.adjType = "visible";
12599 }
12600 schedGroup = Process.THREAD_GROUP_DEFAULT;
12601 app.hidden = false;
12602 app.foregroundActivities = true;
12603 break;
12604 } else if (r.state == ActivityState.PAUSING || r.state == ActivityState.PAUSED
12605 || r.state == ActivityState.STOPPING) {
12606 // Only upgrade adjustment.
12607 if (adj > PERCEPTIBLE_APP_ADJ) {
12608 adj = PERCEPTIBLE_APP_ADJ;
12609 app.adjType = "stopping";
12610 }
12611 app.foregroundActivities = true;
12612 }
12613 }
12614 }
12615
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012616 if (adj > PERCEPTIBLE_APP_ADJ) {
12617 if (app.foregroundServices) {
12618 // The user is aware of this app, so make it visible.
12619 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012620 app.adjType = "foreground-service";
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012621 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012622 } else if (app.forcingToForeground != null) {
12623 // The user is aware of this app, so make it visible.
12624 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012625 app.adjType = "force-foreground";
12626 app.adjSource = app.forcingToForeground;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012627 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012628 }
12629 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012630
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012631 if (adj > HEAVY_WEIGHT_APP_ADJ && app == mHeavyWeightProcess) {
12632 // We don't want to kill the current heavy-weight process.
12633 adj = HEAVY_WEIGHT_APP_ADJ;
12634 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
12635 app.adjType = "heavy";
12636 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012637
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012638 if (adj > HOME_APP_ADJ && app == mHomeProcess) {
12639 // This process is hosting what we currently consider to be the
12640 // home app, so we don't want to let it go into the background.
12641 adj = HOME_APP_ADJ;
12642 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
12643 app.adjType = "home";
12644 }
12645
Joe Onorato8a9b2202010-02-26 18:56:32 -080012646 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012647
The Android Open Source Project4df24232009-03-05 14:34:35 -080012648 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012649 // there are applications dependent on our services or providers, but
12650 // this gives us a baseline and makes sure we don't get into an
12651 // infinite recursion.
12652 app.adjSeq = mAdjSeq;
12653 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012654
Christopher Tate6fa95972009-06-05 18:43:55 -070012655 if (mBackupTarget != null && app == mBackupTarget.app) {
12656 // If possible we want to avoid killing apps while they're being backed up
12657 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012658 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070012659 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012660 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012661 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070012662 }
12663 }
12664
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012665 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
12666 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012667 final long now = SystemClock.uptimeMillis();
12668 // This process is more important if the top activity is
12669 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070012670 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012671 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012672 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012673 if (s.startRequested) {
12674 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
12675 // This service has seen some activity within
12676 // recent memory, so we will keep its process ahead
12677 // of the background processes.
12678 if (adj > SECONDARY_SERVER_ADJ) {
12679 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012680 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012681 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012682 }
12683 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012684 // If we have let the service slide into the background
12685 // state, still have some text describing what it is doing
12686 // even though the service no longer has an impact.
12687 if (adj > SECONDARY_SERVER_ADJ) {
12688 app.adjType = "started-bg-services";
12689 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012690 // Don't kill this process because it is doing work; it
12691 // has said it is doing work.
12692 app.keeping = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012693 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012694 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
12695 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012696 Iterator<ArrayList<ConnectionRecord>> kt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012697 = s.connections.values().iterator();
12698 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012699 ArrayList<ConnectionRecord> clist = kt.next();
12700 for (int i=0; i<clist.size() && adj > FOREGROUND_APP_ADJ; i++) {
12701 // XXX should compute this based on the max of
12702 // all connected clients.
12703 ConnectionRecord cr = clist.get(i);
12704 if (cr.binding.client == app) {
12705 // Binding to ourself is not interesting.
12706 continue;
12707 }
12708 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
12709 ProcessRecord client = cr.binding.client;
12710 int myHiddenAdj = hiddenAdj;
12711 if (myHiddenAdj > client.hiddenAdj) {
12712 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
12713 myHiddenAdj = client.hiddenAdj;
12714 } else {
12715 myHiddenAdj = VISIBLE_APP_ADJ;
12716 }
12717 }
12718 int clientAdj = computeOomAdjLocked(
12719 client, myHiddenAdj, TOP_APP, true);
12720 if (adj > clientAdj) {
12721 adj = clientAdj >= VISIBLE_APP_ADJ
12722 ? clientAdj : VISIBLE_APP_ADJ;
12723 if (!client.hidden) {
12724 app.hidden = false;
12725 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012726 if (client.keeping) {
12727 app.keeping = true;
12728 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012729 app.adjType = "service";
12730 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12731 .REASON_SERVICE_IN_USE;
12732 app.adjSource = cr.binding.client;
12733 app.adjTarget = s.name;
12734 }
12735 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
12736 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
12737 schedGroup = Process.THREAD_GROUP_DEFAULT;
12738 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012739 }
12740 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012741 ActivityRecord a = cr.activity;
12742 //if (a != null) {
12743 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
12744 //}
12745 if (a != null && adj > FOREGROUND_APP_ADJ &&
12746 (a.state == ActivityState.RESUMED
12747 || a.state == ActivityState.PAUSING)) {
12748 adj = FOREGROUND_APP_ADJ;
12749 schedGroup = Process.THREAD_GROUP_DEFAULT;
12750 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012751 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012752 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12753 .REASON_SERVICE_IN_USE;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012754 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012755 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012756 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012757 }
12758 }
12759 }
12760 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012761
Dianne Hackborn287952c2010-09-22 22:34:31 -070012762 // Finally, if this process has active services running in it, we
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012763 // would like to avoid killing it unless it would prevent the current
12764 // application from running. By default we put the process in
12765 // with the rest of the background processes; as we scan through
12766 // its services we may bump it up from there.
12767 if (adj > hiddenAdj) {
12768 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012769 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012770 app.adjType = "bg-services";
12771 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012772 }
12773
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012774 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
12775 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012776 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012777 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
12778 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012779 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012780 if (cpr.clients.size() != 0) {
12781 Iterator<ProcessRecord> kt = cpr.clients.iterator();
12782 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
12783 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070012784 if (client == app) {
12785 // Being our own client is not interesting.
12786 continue;
12787 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012788 int myHiddenAdj = hiddenAdj;
12789 if (myHiddenAdj > client.hiddenAdj) {
12790 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
12791 myHiddenAdj = client.hiddenAdj;
12792 } else {
12793 myHiddenAdj = FOREGROUND_APP_ADJ;
12794 }
12795 }
12796 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012797 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012798 if (adj > clientAdj) {
12799 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012800 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012801 if (!client.hidden) {
12802 app.hidden = false;
12803 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012804 if (client.keeping) {
12805 app.keeping = true;
12806 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012807 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012808 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12809 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012810 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012811 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012812 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012813 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
12814 schedGroup = Process.THREAD_GROUP_DEFAULT;
12815 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012816 }
12817 }
12818 // If the provider has external (non-framework) process
12819 // dependencies, ensure that its adjustment is at least
12820 // FOREGROUND_APP_ADJ.
12821 if (cpr.externals != 0) {
12822 if (adj > FOREGROUND_APP_ADJ) {
12823 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012824 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012825 app.hidden = false;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012826 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012827 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012828 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012829 }
12830 }
12831 }
12832 }
12833
12834 app.curRawAdj = adj;
12835
Joe Onorato8a9b2202010-02-26 18:56:32 -080012836 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012837 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
12838 if (adj > app.maxAdj) {
12839 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070012840 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012841 schedGroup = Process.THREAD_GROUP_DEFAULT;
12842 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012843 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012844 if (adj < HIDDEN_APP_MIN_ADJ) {
12845 app.keeping = true;
12846 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012847
12848 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012849 app.curSchedGroup = schedGroup;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012850
12851 if (hadForegroundActivities != app.foregroundActivities) {
Jeff Sharkey287bd832011-05-28 19:36:26 -070012852 mHandler.obtainMessage(DISPATCH_FOREGROUND_ACTIVITIES_CHANGED, app.pid, app.info.uid,
12853 app.foregroundActivities).sendToTarget();
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012854 }
12855
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012856 return adj;
12857 }
12858
12859 /**
12860 * Ask a given process to GC right now.
12861 */
12862 final void performAppGcLocked(ProcessRecord app) {
12863 try {
12864 app.lastRequestedGc = SystemClock.uptimeMillis();
12865 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012866 if (app.reportLowMemory) {
12867 app.reportLowMemory = false;
12868 app.thread.scheduleLowMemory();
12869 } else {
12870 app.thread.processInBackground();
12871 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012872 }
12873 } catch (Exception e) {
12874 // whatever.
12875 }
12876 }
12877
12878 /**
12879 * Returns true if things are idle enough to perform GCs.
12880 */
Josh Bartel7f208742010-02-25 11:01:44 -060012881 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012882 return mParallelBroadcasts.size() == 0
12883 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012884 && (mSleeping || (mMainStack.mResumedActivity != null &&
12885 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012886 }
12887
12888 /**
12889 * Perform GCs on all processes that are waiting for it, but only
12890 * if things are idle.
12891 */
12892 final void performAppGcsLocked() {
12893 final int N = mProcessesToGc.size();
12894 if (N <= 0) {
12895 return;
12896 }
Josh Bartel7f208742010-02-25 11:01:44 -060012897 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012898 while (mProcessesToGc.size() > 0) {
12899 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070012900 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012901 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
12902 <= SystemClock.uptimeMillis()) {
12903 // To avoid spamming the system, we will GC processes one
12904 // at a time, waiting a few seconds between each.
12905 performAppGcLocked(proc);
12906 scheduleAppGcsLocked();
12907 return;
12908 } else {
12909 // It hasn't been long enough since we last GCed this
12910 // process... put it in the list to wait for its time.
12911 addProcessToGcListLocked(proc);
12912 break;
12913 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012914 }
12915 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012916
12917 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012918 }
12919 }
12920
12921 /**
12922 * If all looks good, perform GCs on all processes waiting for them.
12923 */
12924 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060012925 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012926 performAppGcsLocked();
12927 return;
12928 }
12929 // Still not idle, wait some more.
12930 scheduleAppGcsLocked();
12931 }
12932
12933 /**
12934 * Schedule the execution of all pending app GCs.
12935 */
12936 final void scheduleAppGcsLocked() {
12937 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012938
12939 if (mProcessesToGc.size() > 0) {
12940 // Schedule a GC for the time to the next process.
12941 ProcessRecord proc = mProcessesToGc.get(0);
12942 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
12943
12944 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL;
12945 long now = SystemClock.uptimeMillis();
12946 if (when < (now+GC_TIMEOUT)) {
12947 when = now + GC_TIMEOUT;
12948 }
12949 mHandler.sendMessageAtTime(msg, when);
12950 }
12951 }
12952
12953 /**
12954 * Add a process to the array of processes waiting to be GCed. Keeps the
12955 * list in sorted order by the last GC time. The process can't already be
12956 * on the list.
12957 */
12958 final void addProcessToGcListLocked(ProcessRecord proc) {
12959 boolean added = false;
12960 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
12961 if (mProcessesToGc.get(i).lastRequestedGc <
12962 proc.lastRequestedGc) {
12963 added = true;
12964 mProcessesToGc.add(i+1, proc);
12965 break;
12966 }
12967 }
12968 if (!added) {
12969 mProcessesToGc.add(0, proc);
12970 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012971 }
12972
12973 /**
12974 * Set up to ask a process to GC itself. This will either do it
12975 * immediately, or put it on the list of processes to gc the next
12976 * time things are idle.
12977 */
12978 final void scheduleAppGcLocked(ProcessRecord app) {
12979 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012980 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012981 return;
12982 }
12983 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012984 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012985 scheduleAppGcsLocked();
12986 }
12987 }
12988
Dianne Hackborn287952c2010-09-22 22:34:31 -070012989 final void checkExcessivePowerUsageLocked(boolean doKills) {
12990 updateCpuStatsNow();
12991
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070012992 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
Dianne Hackborn287952c2010-09-22 22:34:31 -070012993 boolean doWakeKills = doKills;
12994 boolean doCpuKills = doKills;
12995 if (mLastPowerCheckRealtime == 0) {
12996 doWakeKills = false;
12997 }
12998 if (mLastPowerCheckUptime == 0) {
12999 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013000 }
13001 if (stats.isScreenOn()) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070013002 doWakeKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013003 }
13004 final long curRealtime = SystemClock.elapsedRealtime();
Dianne Hackborn287952c2010-09-22 22:34:31 -070013005 final long realtimeSince = curRealtime - mLastPowerCheckRealtime;
13006 final long curUptime = SystemClock.uptimeMillis();
13007 final long uptimeSince = curUptime - mLastPowerCheckUptime;
13008 mLastPowerCheckRealtime = curRealtime;
13009 mLastPowerCheckUptime = curUptime;
13010 if (realtimeSince < WAKE_LOCK_MIN_CHECK_DURATION) {
13011 doWakeKills = false;
13012 }
13013 if (uptimeSince < CPU_MIN_CHECK_DURATION) {
13014 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013015 }
13016 int i = mLruProcesses.size();
13017 while (i > 0) {
13018 i--;
13019 ProcessRecord app = mLruProcesses.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -070013020 if (!app.keeping) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013021 long wtime;
13022 synchronized (stats) {
13023 wtime = stats.getProcessWakeTime(app.info.uid,
13024 app.pid, curRealtime);
13025 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070013026 long wtimeUsed = wtime - app.lastWakeTime;
13027 long cputimeUsed = app.curCpuTime - app.lastCpuTime;
13028 if (DEBUG_POWER) {
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070013029 StringBuilder sb = new StringBuilder(128);
13030 sb.append("Wake for ");
13031 app.toShortString(sb);
13032 sb.append(": over ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070013033 TimeUtils.formatDuration(realtimeSince, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070013034 sb.append(" used ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070013035 TimeUtils.formatDuration(wtimeUsed, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070013036 sb.append(" (");
Dianne Hackborn287952c2010-09-22 22:34:31 -070013037 sb.append((wtimeUsed*100)/realtimeSince);
13038 sb.append("%)");
13039 Slog.i(TAG, sb.toString());
13040 sb.setLength(0);
13041 sb.append("CPU for ");
13042 app.toShortString(sb);
13043 sb.append(": over ");
13044 TimeUtils.formatDuration(uptimeSince, sb);
13045 sb.append(" used ");
13046 TimeUtils.formatDuration(cputimeUsed, sb);
13047 sb.append(" (");
13048 sb.append((cputimeUsed*100)/uptimeSince);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070013049 sb.append("%)");
13050 Slog.i(TAG, sb.toString());
13051 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013052 // If a process has held a wake lock for more
13053 // than 50% of the time during this period,
13054 // that sounds pad. Kill!
Dianne Hackborn287952c2010-09-22 22:34:31 -070013055 if (doWakeKills && realtimeSince > 0
13056 && ((wtimeUsed*100)/realtimeSince) >= 50) {
13057 synchronized (stats) {
13058 stats.reportExcessiveWakeLocked(app.info.uid, app.processName,
13059 realtimeSince, wtimeUsed);
13060 }
13061 Slog.w(TAG, "Excessive wake lock in " + app.processName
13062 + " (pid " + app.pid + "): held " + wtimeUsed
13063 + " during " + realtimeSince);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013064 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13065 app.processName, app.setAdj, "excessive wake lock");
13066 Process.killProcessQuiet(app.pid);
Dianne Hackborn287952c2010-09-22 22:34:31 -070013067 } else if (doCpuKills && uptimeSince > 0
13068 && ((cputimeUsed*100)/uptimeSince) >= 50) {
13069 synchronized (stats) {
13070 stats.reportExcessiveCpuLocked(app.info.uid, app.processName,
13071 uptimeSince, cputimeUsed);
13072 }
13073 Slog.w(TAG, "Excessive CPU in " + app.processName
13074 + " (pid " + app.pid + "): used " + cputimeUsed
13075 + " during " + uptimeSince);
13076 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13077 app.processName, app.setAdj, "excessive cpu");
13078 Process.killProcessQuiet(app.pid);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013079 } else {
13080 app.lastWakeTime = wtime;
Dianne Hackborn287952c2010-09-22 22:34:31 -070013081 app.lastCpuTime = app.curCpuTime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013082 }
13083 }
13084 }
13085 }
13086
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013087 private final boolean updateOomAdjLocked(
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013088 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013089 app.hiddenAdj = hiddenAdj;
13090
13091 if (app.thread == null) {
13092 return true;
13093 }
13094
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013095 boolean success = true;
13096
Dianne Hackborn287952c2010-09-22 22:34:31 -070013097 final boolean wasKeeping = app.keeping;
13098
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013099 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013100
Jeff Brown10e89712011-07-08 18:52:57 -070013101 if (app.curRawAdj != app.setRawAdj) {
13102 if (app.curRawAdj > FOREGROUND_APP_ADJ
13103 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
13104 // If this app is transitioning from foreground to
13105 // non-foreground, have it do a gc.
13106 scheduleAppGcLocked(app);
13107 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
13108 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
13109 // Likewise do a gc when an app is moving in to the
13110 // background (such as a service stopping).
13111 scheduleAppGcLocked(app);
13112 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070013113
Jeff Brown10e89712011-07-08 18:52:57 -070013114 if (wasKeeping && !app.keeping) {
13115 // This app is no longer something we want to keep. Note
13116 // its current wake lock time to later know to kill it if
13117 // it is not behaving well.
13118 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
13119 synchronized (stats) {
13120 app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
13121 app.pid, SystemClock.elapsedRealtime());
13122 }
13123 app.lastCpuTime = app.curCpuTime;
13124 }
13125
13126 app.setRawAdj = app.curRawAdj;
13127 }
13128 if (adj != app.setAdj) {
13129 if (Process.setOomAdj(app.pid, adj)) {
13130 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
13131 TAG, "Set app " + app.processName +
13132 " oom adj to " + adj);
13133 app.setAdj = adj;
13134 } else {
13135 success = false;
13136 }
13137 }
13138 if (app.setSchedGroup != app.curSchedGroup) {
13139 app.setSchedGroup = app.curSchedGroup;
13140 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
13141 "Setting process group of " + app.processName
13142 + " to " + app.curSchedGroup);
13143 if (app.waitingToKill != null &&
13144 app.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {
13145 Slog.i(TAG, "Killing " + app.toShortString() + ": " + app.waitingToKill);
13146 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13147 app.processName, app.setAdj, app.waitingToKill);
13148 Process.killProcessQuiet(app.pid);
13149 } else {
13150 if (true) {
13151 long oldId = Binder.clearCallingIdentity();
13152 try {
13153 Process.setProcessGroup(app.pid, app.curSchedGroup);
13154 } catch (Exception e) {
13155 Slog.w(TAG, "Failed setting process group of " + app.pid
13156 + " to " + app.curSchedGroup);
13157 e.printStackTrace();
13158 } finally {
13159 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013160 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013161 }
Jeff Brown10e89712011-07-08 18:52:57 -070013162 if (false) {
13163 if (app.thread != null) {
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013164 try {
Jeff Brown10e89712011-07-08 18:52:57 -070013165 app.thread.setSchedulingGroup(app.curSchedGroup);
13166 } catch (RemoteException e) {
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013167 }
13168 }
13169 }
13170 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013171 }
13172
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013173 return success;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013174 }
13175
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013176 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013177 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013178 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013179 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013180 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013181 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013182 }
13183 }
13184 return resumedActivity;
13185 }
13186
13187 private final boolean updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013188 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013189 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
13190 int curAdj = app.curAdj;
13191 final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
13192 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
13193
13194 mAdjSeq++;
13195
13196 final boolean res = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
13197 if (res) {
13198 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
13199 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
13200 if (nowHidden != wasHidden) {
13201 // Changed to/from hidden state, so apps after it in the LRU
13202 // list may also be changed.
13203 updateOomAdjLocked();
13204 }
13205 }
13206 return res;
13207 }
13208
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013209 final boolean updateOomAdjLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013210 boolean didOomAdj = true;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013211 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013212 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
13213
13214 if (false) {
13215 RuntimeException e = new RuntimeException();
13216 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080013217 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013218 }
13219
13220 mAdjSeq++;
13221
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013222 // Let's determine how many processes we have running vs.
13223 // how many slots we have for background processes; we may want
13224 // to put multiple processes in a slot of there are enough of
13225 // them.
13226 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
13227 int factor = (mLruProcesses.size()-4)/numSlots;
13228 if (factor < 1) factor = 1;
13229 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070013230 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013231
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013232 // First try updating the OOM adjustment for each of the
13233 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013234 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013235 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
13236 while (i > 0) {
13237 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013238 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013239 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013240 if (updateOomAdjLocked(app, curHiddenAdj, TOP_APP)) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013241 if (curHiddenAdj < EMPTY_APP_ADJ
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013242 && app.curAdj == curHiddenAdj) {
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013243 step++;
13244 if (step >= factor) {
13245 step = 0;
13246 curHiddenAdj++;
13247 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013248 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070013249 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn149427c2010-04-23 14:20:03 -070013250 if (!app.killedBackground) {
13251 numHidden++;
13252 if (numHidden > MAX_HIDDEN_APPS) {
Dianne Hackborn906497c2010-05-10 15:57:38 -070013253 Slog.i(TAG, "No longer want " + app.processName
13254 + " (pid " + app.pid + "): hidden #" + numHidden);
Dianne Hackborn149427c2010-04-23 14:20:03 -070013255 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13256 app.processName, app.setAdj, "too many background");
13257 app.killedBackground = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -070013258 Process.killProcessQuiet(app.pid);
Dianne Hackborn149427c2010-04-23 14:20:03 -070013259 }
Dianne Hackborn8633e682010-04-22 16:03:41 -070013260 }
13261 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013262 } else {
13263 didOomAdj = false;
13264 }
13265 }
13266
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013267 // If we return false, we will fall back on killing processes to
13268 // have a fixed limit. Do this if a limit has been requested; else
13269 // only return false if one of the adjustments failed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013270 return ENFORCE_PROCESS_LIMIT || mProcessLimit > 0 ? false : didOomAdj;
13271 }
13272
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013273 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013274 synchronized (this) {
13275 int i;
13276
13277 // First remove any unused application processes whose package
13278 // has been removed.
13279 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
13280 final ProcessRecord app = mRemovedProcesses.get(i);
13281 if (app.activities.size() == 0
13282 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013283 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013284 TAG, "Exiting empty application process "
13285 + app.processName + " ("
13286 + (app.thread != null ? app.thread.asBinder() : null)
13287 + ")\n");
13288 if (app.pid > 0 && app.pid != MY_PID) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070013289 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13290 app.processName, app.setAdj, "empty");
13291 Process.killProcessQuiet(app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013292 } else {
13293 try {
13294 app.thread.scheduleExit();
13295 } catch (Exception e) {
13296 // Ignore exceptions.
13297 }
13298 }
13299 cleanUpApplicationRecordLocked(app, false, -1);
13300 mRemovedProcesses.remove(i);
13301
13302 if (app.persistent) {
13303 if (app.persistent) {
13304 addAppLocked(app.info);
13305 }
13306 }
13307 }
13308 }
13309
13310 // Now try updating the OOM adjustment for each of the
13311 // application processes based on their current state.
13312 // If the setOomAdj() API is not supported, then go with our
13313 // back-up plan...
13314 if (!updateOomAdjLocked()) {
13315
13316 // Count how many processes are running services.
13317 int numServiceProcs = 0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013318 for (i=mLruProcesses.size()-1; i>=0; i--) {
13319 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013320
13321 if (app.persistent || app.services.size() != 0
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070013322 || app.curReceiver != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013323 // Don't count processes holding services against our
13324 // maximum process count.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013325 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013326 TAG, "Not trimming app " + app + " with services: "
13327 + app.services);
13328 numServiceProcs++;
13329 }
13330 }
13331
13332 int curMaxProcs = mProcessLimit;
13333 if (curMaxProcs <= 0) curMaxProcs = MAX_PROCESSES;
13334 if (mAlwaysFinishActivities) {
13335 curMaxProcs = 1;
13336 }
13337 curMaxProcs += numServiceProcs;
13338
13339 // Quit as many processes as we can to get down to the desired
13340 // process count. First remove any processes that no longer
13341 // have activites running in them.
13342 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013343 i<mLruProcesses.size()
13344 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013345 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013346 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013347 // Quit an application only if it is not currently
13348 // running any activities.
13349 if (!app.persistent && app.activities.size() == 0
13350 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013351 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013352 TAG, "Exiting empty application process "
13353 + app.processName + " ("
13354 + (app.thread != null ? app.thread.asBinder() : null)
13355 + ")\n");
13356 if (app.pid > 0 && app.pid != MY_PID) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070013357 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13358 app.processName, app.setAdj, "empty");
13359 Process.killProcessQuiet(app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013360 } else {
13361 try {
13362 app.thread.scheduleExit();
13363 } catch (Exception e) {
13364 // Ignore exceptions.
13365 }
13366 }
13367 // todo: For now we assume the application is not buggy
13368 // or evil, and will quit as a result of our request.
13369 // Eventually we need to drive this off of the death
13370 // notification, and kill the process if it takes too long.
13371 cleanUpApplicationRecordLocked(app, false, i);
13372 i--;
13373 }
13374 }
13375
13376 // If we still have too many processes, now from the least
13377 // recently used process we start finishing activities.
Joe Onorato43a17652011-04-06 19:22:23 -070013378 if (false) Slog.v(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013379 TAG, "*** NOW HAVE " + mLruProcesses.size() +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013380 " of " + curMaxProcs + " processes");
13381 for ( i=0;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013382 i<mLruProcesses.size()
13383 && mLruProcesses.size() > curMaxProcs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013384 i++) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013385 final ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013386 // Quit the application only if we have a state saved for
13387 // all of its activities.
13388 boolean canQuit = !app.persistent && app.curReceiver == null
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070013389 && app.services.size() == 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013390 int NUMA = app.activities.size();
13391 int j;
Joe Onorato43a17652011-04-06 19:22:23 -070013392 if (false) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013393 TAG, "Looking to quit " + app.processName);
13394 for (j=0; j<NUMA && canQuit; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013395 ActivityRecord r = app.activities.get(j);
Joe Onorato43a17652011-04-06 19:22:23 -070013396 if (false) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013397 TAG, " " + r.intent.getComponent().flattenToShortString()
13398 + ": frozen=" + r.haveState + ", visible=" + r.visible);
13399 canQuit = (r.haveState || !r.stateNotNeeded)
13400 && !r.visible && r.stopped;
13401 }
13402 if (canQuit) {
13403 // Finish all of the activities, and then the app itself.
13404 for (j=0; j<NUMA; j++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013405 ActivityRecord r = app.activities.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013406 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013407 r.stack.destroyActivityLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013408 }
13409 r.resultTo = null;
13410 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080013411 Slog.i(TAG, "Exiting application process "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013412 + app.processName + " ("
13413 + (app.thread != null ? app.thread.asBinder() : null)
13414 + ")\n");
13415 if (app.pid > 0 && app.pid != MY_PID) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070013416 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13417 app.processName, app.setAdj, "old background");
13418 Process.killProcessQuiet(app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013419 } else {
13420 try {
13421 app.thread.scheduleExit();
13422 } catch (Exception e) {
13423 // Ignore exceptions.
13424 }
13425 }
13426 // todo: For now we assume the application is not buggy
13427 // or evil, and will quit as a result of our request.
13428 // Eventually we need to drive this off of the death
13429 // notification, and kill the process if it takes too long.
13430 cleanUpApplicationRecordLocked(app, false, i);
13431 i--;
13432 //dump();
13433 }
13434 }
13435
13436 }
13437
13438 int curMaxActivities = MAX_ACTIVITIES;
13439 if (mAlwaysFinishActivities) {
13440 curMaxActivities = 1;
13441 }
13442
13443 // Finally, if there are too many activities now running, try to
13444 // finish as many as we can to get back down to the limit.
13445 for ( i=0;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013446 i<mMainStack.mLRUActivities.size()
13447 && mMainStack.mLRUActivities.size() > curMaxActivities;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013448 i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013449 final ActivityRecord r
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013450 = (ActivityRecord)mMainStack.mLRUActivities.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013451
13452 // We can finish this one if we have its icicle saved and
13453 // it is not persistent.
13454 if ((r.haveState || !r.stateNotNeeded) && !r.visible
Dianne Hackborn3c4c2b72010-10-05 18:07:54 -070013455 && r.stopped && !r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013456 final int origSize = mMainStack.mLRUActivities.size();
13457 r.stack.destroyActivityLocked(r, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013458
13459 // This will remove it from the LRU list, so keep
13460 // our index at the same value. Note that this check to
13461 // see if the size changes is just paranoia -- if
13462 // something unexpected happens, we don't want to end up
13463 // in an infinite loop.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013464 if (origSize > mMainStack.mLRUActivities.size()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013465 i--;
13466 }
13467 }
13468 }
13469 }
13470 }
13471
13472 /** This method sends the specified signal to each of the persistent apps */
13473 public void signalPersistentProcesses(int sig) throws RemoteException {
13474 if (sig != Process.SIGNAL_USR1) {
13475 throw new SecurityException("Only SIGNAL_USR1 is allowed");
13476 }
13477
13478 synchronized (this) {
13479 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
13480 != PackageManager.PERMISSION_GRANTED) {
13481 throw new SecurityException("Requires permission "
13482 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
13483 }
13484
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013485 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
13486 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013487 if (r.thread != null && r.persistent) {
13488 Process.sendSignal(r.pid, sig);
13489 }
13490 }
13491 }
13492 }
13493
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013494 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013495 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013496
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013497 try {
13498 synchronized (this) {
13499 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
13500 // its own permission.
13501 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
13502 != PackageManager.PERMISSION_GRANTED) {
13503 throw new SecurityException("Requires permission "
13504 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013505 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013506
13507 if (start && fd == null) {
13508 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013509 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013510
13511 ProcessRecord proc = null;
13512 try {
13513 int pid = Integer.parseInt(process);
13514 synchronized (mPidsSelfLocked) {
13515 proc = mPidsSelfLocked.get(pid);
13516 }
13517 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013518 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013519
13520 if (proc == null) {
13521 HashMap<String, SparseArray<ProcessRecord>> all
13522 = mProcessNames.getMap();
13523 SparseArray<ProcessRecord> procs = all.get(process);
13524 if (procs != null && procs.size() > 0) {
13525 proc = procs.valueAt(0);
13526 }
13527 }
13528
13529 if (proc == null || proc.thread == null) {
13530 throw new IllegalArgumentException("Unknown process: " + process);
13531 }
13532
Dianne Hackbornf02e57b2011-03-01 22:21:04 -080013533 boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
13534 if (!isDebuggable) {
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013535 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
13536 throw new SecurityException("Process not debuggable: " + proc);
13537 }
13538 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013539
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013540 proc.thread.profilerControl(start, path, fd);
13541 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013542 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013543 }
13544 } catch (RemoteException e) {
13545 throw new IllegalStateException("Process disappeared");
13546 } finally {
13547 if (fd != null) {
13548 try {
13549 fd.close();
13550 } catch (IOException e) {
13551 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013552 }
13553 }
13554 }
Andy McFadden824c5102010-07-09 16:26:57 -070013555
13556 public boolean dumpHeap(String process, boolean managed,
13557 String path, ParcelFileDescriptor fd) throws RemoteException {
13558
13559 try {
13560 synchronized (this) {
13561 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
13562 // its own permission (same as profileControl).
13563 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
13564 != PackageManager.PERMISSION_GRANTED) {
13565 throw new SecurityException("Requires permission "
13566 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
13567 }
13568
13569 if (fd == null) {
13570 throw new IllegalArgumentException("null fd");
13571 }
13572
13573 ProcessRecord proc = null;
13574 try {
13575 int pid = Integer.parseInt(process);
13576 synchronized (mPidsSelfLocked) {
13577 proc = mPidsSelfLocked.get(pid);
13578 }
13579 } catch (NumberFormatException e) {
13580 }
13581
13582 if (proc == null) {
13583 HashMap<String, SparseArray<ProcessRecord>> all
13584 = mProcessNames.getMap();
13585 SparseArray<ProcessRecord> procs = all.get(process);
13586 if (procs != null && procs.size() > 0) {
13587 proc = procs.valueAt(0);
13588 }
13589 }
13590
13591 if (proc == null || proc.thread == null) {
13592 throw new IllegalArgumentException("Unknown process: " + process);
13593 }
13594
Dianne Hackbornf02e57b2011-03-01 22:21:04 -080013595 boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
13596 if (!isDebuggable) {
Andy McFadden824c5102010-07-09 16:26:57 -070013597 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
13598 throw new SecurityException("Process not debuggable: " + proc);
13599 }
13600 }
13601
13602 proc.thread.dumpHeap(managed, path, fd);
13603 fd = null;
13604 return true;
13605 }
13606 } catch (RemoteException e) {
13607 throw new IllegalStateException("Process disappeared");
13608 } finally {
13609 if (fd != null) {
13610 try {
13611 fd.close();
13612 } catch (IOException e) {
13613 }
13614 }
13615 }
13616 }
13617
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013618 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
13619 public void monitor() {
13620 synchronized (this) { }
13621 }
Svetoslav Ganov54d068e2011-03-02 12:58:40 -080013622
13623 public void onCoreSettingsChange(Bundle settings) {
13624 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
13625 ProcessRecord processRecord = mLruProcesses.get(i);
13626 try {
13627 if (processRecord.thread != null) {
13628 processRecord.thread.setCoreSettings(settings);
13629 }
13630 } catch (RemoteException re) {
13631 /* ignore */
13632 }
13633 }
13634 }
Amith Yamasani4b2e9342011-03-31 12:38:53 -070013635
13636 // Multi-user methods
13637
13638 public boolean switchUser(int userid) {
13639 // TODO
13640 return true;
13641 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013642}