blob: a07aa608d07690367322949ea638f58b20e4a097 [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 Hackborn45ce8642011-07-14 16:10:16 -070021import com.android.internal.os.ProcessStats;
Dianne Hackbornde7faf62009-06-30 13:27:30 -070022import com.android.server.AttributeCache;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080023import com.android.server.IntentResolver;
24import com.android.server.ProcessMap;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080025import 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;
48import android.app.Instrumentation;
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070049import android.app.Notification;
Dianne Hackborn860755f2010-06-03 18:47:52 -070050import android.app.NotificationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080051import android.app.PendingIntent;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070052import android.app.Service;
Christopher Tate45281862010-03-05 15:46:30 -080053import android.app.backup.IBackupManager;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020054import android.content.ActivityNotFoundException;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080055import android.content.BroadcastReceiver;
Dianne Hackbornce86ba82011-07-13 19:33:41 -070056import android.content.ComponentCallbacks;
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
Dianne Hackbornf02e57b2011-03-01 22:21:04 -0800184 private static final String SYSTEM_DEBUGGABLE = "ro.debuggable";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800185
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800186 // Maximum number of recent tasks that we can remember.
187 static final int MAX_RECENT_TASKS = 20;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700188
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700189 // Amount of time after a call to stopAppSwitches() during which we will
190 // prevent further untrusted switches from happening.
191 static final long APP_SWITCH_DELAY_TIME = 5*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800192
193 // How long we wait for a launched process to attach to the activity manager
194 // before we decide it's never going to come up for real.
195 static final int PROC_START_TIMEOUT = 10*1000;
196
Jeff Brown3f9dd282011-07-08 20:02:19 -0700197 // How long we wait for a launched process to attach to the activity manager
198 // before we decide it's never going to come up for real, when the process was
199 // started with a wrapper for instrumentation (such as Valgrind) because it
200 // could take much longer than usual.
201 static final int PROC_START_TIMEOUT_WITH_WRAPPER = 300*1000;
202
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800203 // How long to wait after going idle before forcing apps to GC.
204 static final int GC_TIMEOUT = 5*1000;
205
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700206 // The minimum amount of time between successive GC requests for a process.
207 static final int GC_MIN_INTERVAL = 60*1000;
208
Dianne Hackborn287952c2010-09-22 22:34:31 -0700209 // The rate at which we check for apps using excessive power -- 15 mins.
210 static final int POWER_CHECK_DELAY = (DEBUG_POWER_QUICK ? 2 : 15) * 60*1000;
211
212 // The minimum sample duration we will allow before deciding we have
213 // enough data on wake locks to start killing things.
214 static final int WAKE_LOCK_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
215
216 // The minimum sample duration we will allow before deciding we have
217 // enough data on CPU usage to start killing things.
218 static final int CPU_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700219
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800220 // How long we allow a receiver to run before giving up on it.
221 static final int BROADCAST_TIMEOUT = 10*1000;
222
223 // How long we wait for a service to finish executing.
224 static final int SERVICE_TIMEOUT = 20*1000;
225
226 // How long a service needs to be running until restarting its process
227 // is no longer considered to be a relaunch of the service.
228 static final int SERVICE_RESTART_DURATION = 5*1000;
229
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700230 // How long a service needs to be running until it will start back at
231 // SERVICE_RESTART_DURATION after being killed.
232 static final int SERVICE_RESET_RUN_DURATION = 60*1000;
233
234 // Multiplying factor to increase restart duration time by, for each time
235 // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
236 static final int SERVICE_RESTART_DURATION_FACTOR = 4;
237
238 // The minimum amount of time between restarting services that we allow.
239 // That is, when multiple services are restarting, we won't allow each
240 // to restart less than this amount of time from the last one.
241 static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
242
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800243 // Maximum amount of time for there to be no activity on a service before
244 // we consider it non-essential and allow its process to go on the
245 // LRU background list.
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700246 static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800247
248 // How long we wait until we timeout on key dispatching.
249 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
250
251 // The minimum time we allow between crashes, for us to consider this
252 // application to be bad and stop and its services and reject broadcasts.
253 static final int MIN_CRASH_INTERVAL = 60*1000;
254
255 // How long we wait until we timeout on key dispatching during instrumentation.
256 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
257
258 // OOM adjustments for processes in various states:
259
260 // This is a process without anything currently running in it. Definitely
261 // the first to go! Value set in system/rootdir/init.rc on startup.
262 // This value is initalized in the constructor, careful when refering to
263 // this static variable externally.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800264 static final int EMPTY_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800265
266 // This is a process only hosting activities that are not visible,
267 // so it can be killed without any disruption. Value set in
268 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800269 static final int HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800270 static int HIDDEN_APP_MIN_ADJ;
271
The Android Open Source Project4df24232009-03-05 14:34:35 -0800272 // This is a process holding the home application -- we want to try
273 // avoiding killing it, even if it would normally be in the background,
274 // because the user interacts with it so much.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800275 static final int HOME_APP_ADJ;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800276
Christopher Tate6fa95972009-06-05 18:43:55 -0700277 // This is a process currently hosting a backup operation. Killing it
278 // is not entirely fatal but is generally a bad idea.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800279 static final int BACKUP_APP_ADJ;
Christopher Tate6fa95972009-06-05 18:43:55 -0700280
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800281 // This is a process holding a secondary server -- killing it will not
282 // have much of an impact as far as the user is concerned. Value set in
283 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800284 static final int SECONDARY_SERVER_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800285
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700286 // This is a process with a heavy-weight application. It is in the
287 // background, but we want to try to avoid killing it. Value set in
288 // system/rootdir/init.rc on startup.
289 static final int HEAVY_WEIGHT_APP_ADJ;
290
291 // This is a process only hosting components that are perceptible to the
292 // user, and we really want to avoid killing them, but they are not
293 // immediately visible. An example is background music playback. Value set in
294 // system/rootdir/init.rc on startup.
295 static final int PERCEPTIBLE_APP_ADJ;
296
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800297 // This is a process only hosting activities that are visible to the
298 // user, so we'd prefer they don't disappear. Value set in
299 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800300 static final int VISIBLE_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800301
302 // This is the process running the current foreground app. We'd really
303 // rather not kill it! Value set in system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800304 static final int FOREGROUND_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800305
306 // This is a process running a core server, such as telephony. Definitely
307 // don't want to kill it, but doing so is not completely fatal.
308 static final int CORE_SERVER_ADJ = -12;
309
310 // The system process runs at the default adjustment.
311 static final int SYSTEM_ADJ = -16;
312
313 // Memory pages are 4K.
314 static final int PAGE_SIZE = 4*1024;
315
316 // Corresponding memory levels for above adjustments.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800317 static final int EMPTY_APP_MEM;
318 static final int HIDDEN_APP_MEM;
319 static final int HOME_APP_MEM;
320 static final int BACKUP_APP_MEM;
321 static final int SECONDARY_SERVER_MEM;
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700322 static final int HEAVY_WEIGHT_APP_MEM;
323 static final int PERCEPTIBLE_APP_MEM;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800324 static final int VISIBLE_APP_MEM;
325 static final int FOREGROUND_APP_MEM;
326
327 // The minimum number of hidden apps we want to be able to keep around,
328 // without empty apps being able to push them out of memory.
329 static final int MIN_HIDDEN_APPS = 2;
330
Dianne Hackborn8633e682010-04-22 16:03:41 -0700331 // The maximum number of hidden processes we will keep around before
332 // killing them; this is just a control to not let us go too crazy with
333 // keeping around processes on devices with large amounts of RAM.
334 static final int MAX_HIDDEN_APPS = 15;
335
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800336 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700337 // been idle for less than 15 seconds.
338 static final long CONTENT_APP_IDLE_OFFSET = 15*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800339
340 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700341 // been idle for less than 120 seconds.
342 static final long EMPTY_APP_IDLE_OFFSET = 120*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800343
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700344 static int getIntProp(String name, boolean allowZero) {
345 String str = SystemProperties.get(name);
346 if (str == null) {
347 throw new IllegalArgumentException("Property not defined: " + name);
348 }
349 int val = Integer.valueOf(str);
350 if (val == 0 && !allowZero) {
351 throw new IllegalArgumentException("Property must not be zero: " + name);
352 }
353 return val;
354 }
355
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800356 static {
357 // These values are set in system/rootdir/init.rc on startup.
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700358 FOREGROUND_APP_ADJ = getIntProp("ro.FOREGROUND_APP_ADJ", true);
359 VISIBLE_APP_ADJ = getIntProp("ro.VISIBLE_APP_ADJ", true);
360 PERCEPTIBLE_APP_ADJ = getIntProp("ro.PERCEPTIBLE_APP_ADJ", true);
361 HEAVY_WEIGHT_APP_ADJ = getIntProp("ro.HEAVY_WEIGHT_APP_ADJ", true);
362 SECONDARY_SERVER_ADJ = getIntProp("ro.SECONDARY_SERVER_ADJ", true);
363 BACKUP_APP_ADJ = getIntProp("ro.BACKUP_APP_ADJ", true);
364 HOME_APP_ADJ = getIntProp("ro.HOME_APP_ADJ", true);
365 HIDDEN_APP_MIN_ADJ = getIntProp("ro.HIDDEN_APP_MIN_ADJ", true);
366 EMPTY_APP_ADJ = getIntProp("ro.EMPTY_APP_ADJ", true);
367 // These days we use the last empty slot for hidden apps as well.
368 HIDDEN_APP_MAX_ADJ = EMPTY_APP_ADJ;
369 FOREGROUND_APP_MEM = getIntProp("ro.FOREGROUND_APP_MEM", false)*PAGE_SIZE;
370 VISIBLE_APP_MEM = getIntProp("ro.VISIBLE_APP_MEM", false)*PAGE_SIZE;
371 PERCEPTIBLE_APP_MEM = getIntProp("ro.PERCEPTIBLE_APP_MEM", false)*PAGE_SIZE;
372 HEAVY_WEIGHT_APP_MEM = getIntProp("ro.HEAVY_WEIGHT_APP_MEM", false)*PAGE_SIZE;
373 SECONDARY_SERVER_MEM = getIntProp("ro.SECONDARY_SERVER_MEM", false)*PAGE_SIZE;
374 BACKUP_APP_MEM = getIntProp("ro.BACKUP_APP_MEM", false)*PAGE_SIZE;
375 HOME_APP_MEM = getIntProp("ro.HOME_APP_MEM", false)*PAGE_SIZE;
376 HIDDEN_APP_MEM = getIntProp("ro.HIDDEN_APP_MEM", false)*PAGE_SIZE;
377 EMPTY_APP_MEM = getIntProp("ro.EMPTY_APP_MEM", false)*PAGE_SIZE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800378 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800379
Dan Egnor42471dd2010-01-07 17:25:22 -0800380 static final int MY_PID = Process.myPid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800381
382 static final String[] EMPTY_STRING_ARRAY = new String[0];
383
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700384 public ActivityStack mMainStack;
385
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800386 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700387 * Description of a request to start a new activity, which has been held
388 * due to app switches being disabled.
389 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700390 static class PendingActivityLaunch {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700391 ActivityRecord r;
392 ActivityRecord sourceRecord;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700393 Uri[] grantedUriPermissions;
394 int grantedMode;
395 boolean onlyIfNeeded;
396 }
397
398 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
399 = new ArrayList<PendingActivityLaunch>();
400
401 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800402 * List of all active broadcasts that are to be executed immediately
403 * (without waiting for another broadcast to finish). Currently this only
404 * contains broadcasts to registered receivers, to avoid spinning up
405 * a bunch of processes to execute IntentReceiver components.
406 */
407 final ArrayList<BroadcastRecord> mParallelBroadcasts
408 = new ArrayList<BroadcastRecord>();
409
410 /**
411 * List of all active broadcasts that are to be executed one at a time.
412 * The object at the top of the list is the currently activity broadcasts;
413 * those after it are waiting for the top to finish..
414 */
415 final ArrayList<BroadcastRecord> mOrderedBroadcasts
416 = new ArrayList<BroadcastRecord>();
417
418 /**
Dianne Hackborn12527f92009-11-11 17:39:50 -0800419 * Historical data of past broadcasts, for debugging.
420 */
421 static final int MAX_BROADCAST_HISTORY = 100;
422 final BroadcastRecord[] mBroadcastHistory
423 = new BroadcastRecord[MAX_BROADCAST_HISTORY];
424
425 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800426 * Set when we current have a BROADCAST_INTENT_MSG in flight.
427 */
428 boolean mBroadcastsScheduled = false;
429
430 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800431 * Activity we have told the window manager to have key focus.
432 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700433 ActivityRecord mFocusedActivity = null;
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700434 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800435 * List of intents that were used to start the most recent tasks.
436 */
Dianne Hackborn0c5001d2011-04-12 18:16:08 -0700437 final ArrayList<TaskRecord> mRecentTasks = new ArrayList<TaskRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800438
439 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800440 * All of the applications we currently have running organized by name.
441 * The keys are strings of the application package name (as
442 * returned by the package manager), and the keys are ApplicationRecord
443 * objects.
444 */
Dianne Hackborn0c5001d2011-04-12 18:16:08 -0700445 final ProcessMap<ProcessRecord> mProcessNames = new ProcessMap<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800446
447 /**
Dianne Hackborn860755f2010-06-03 18:47:52 -0700448 * The currently running heavy-weight process, if any.
449 */
450 ProcessRecord mHeavyWeightProcess = null;
451
452 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800453 * The last time that various processes have crashed.
454 */
455 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
456
457 /**
458 * Set of applications that we consider to be bad, and will reject
459 * incoming broadcasts from (which the user has no control over).
460 * Processes are added to this set when they have crashed twice within
461 * a minimum amount of time; they are removed from it when they are
462 * later restarted (hopefully due to some user action). The value is the
463 * time it was added to the list.
464 */
465 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
466
467 /**
468 * All of the processes we currently have running organized by pid.
469 * The keys are the pid running the application.
470 *
471 * <p>NOTE: This object is protected by its own lock, NOT the global
472 * activity manager lock!
473 */
Dianne Hackborn0c5001d2011-04-12 18:16:08 -0700474 final SparseArray<ProcessRecord> mPidsSelfLocked = new SparseArray<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800475
476 /**
477 * All of the processes that have been forced to be foreground. The key
478 * is the pid of the caller who requested it (we hold a death
479 * link on it).
480 */
481 abstract class ForegroundToken implements IBinder.DeathRecipient {
482 int pid;
483 IBinder token;
484 }
485 final SparseArray<ForegroundToken> mForegroundProcesses
486 = new SparseArray<ForegroundToken>();
487
488 /**
489 * List of records for processes that someone had tried to start before the
490 * system was ready. We don't start them at that point, but ensure they
491 * are started by the time booting is complete.
492 */
493 final ArrayList<ProcessRecord> mProcessesOnHold
494 = new ArrayList<ProcessRecord>();
495
496 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800497 * List of persistent applications that are in the process
498 * of being started.
499 */
500 final ArrayList<ProcessRecord> mPersistentStartingProcesses
501 = new ArrayList<ProcessRecord>();
502
503 /**
504 * Processes that are being forcibly torn down.
505 */
506 final ArrayList<ProcessRecord> mRemovedProcesses
507 = new ArrayList<ProcessRecord>();
508
509 /**
510 * List of running applications, sorted by recent usage.
511 * The first entry in the list is the least recently used.
512 * It contains ApplicationRecord objects. This list does NOT include
513 * any persistent application records (since we never want to exit them).
514 */
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800515 final ArrayList<ProcessRecord> mLruProcesses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800516 = new ArrayList<ProcessRecord>();
517
518 /**
519 * List of processes that should gc as soon as things are idle.
520 */
521 final ArrayList<ProcessRecord> mProcessesToGc
522 = new ArrayList<ProcessRecord>();
523
524 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -0800525 * This is the process holding what we currently consider to be
526 * the "home" activity.
527 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700528 ProcessRecord mHomeProcess;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800529
530 /**
Dianne Hackborne2515ee2011-04-27 18:52:56 -0400531 * Packages that the user has asked to have run in screen size
532 * compatibility mode instead of filling the screen.
533 */
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -0700534 final CompatModePackages mCompatModePackages;
Dianne Hackborne2515ee2011-04-27 18:52:56 -0400535
536 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800537 * Set of PendingResultRecord objects that are currently active.
538 */
539 final HashSet mPendingResultRecords = new HashSet();
540
541 /**
542 * Set of IntentSenderRecord objects that are currently active.
543 */
544 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
545 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
546
547 /**
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -0800548 * Fingerprints (hashCode()) of stack traces that we've
Brad Fitzpatrick143666f2010-06-14 12:40:21 -0700549 * already logged DropBox entries for. Guarded by itself. If
550 * something (rogue user app) forces this over
551 * MAX_DUP_SUPPRESSED_STACKS entries, the contents are cleared.
552 */
553 private final HashSet<Integer> mAlreadyLoggedViolatedStacks = new HashSet<Integer>();
554 private static final int MAX_DUP_SUPPRESSED_STACKS = 5000;
555
556 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -0700557 * Strict Mode background batched logging state.
558 *
559 * The string buffer is guarded by itself, and its lock is also
560 * used to determine if another batched write is already
561 * in-flight.
562 */
563 private final StringBuilder mStrictModeBuffer = new StringBuilder();
564
565 /**
Jeff Brown4d94a762010-09-23 11:33:28 -0700566 * True if we have a pending unexpired BROADCAST_TIMEOUT_MSG posted to our handler.
567 */
568 private boolean mPendingBroadcastTimeoutMessage;
569
570 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800571 * Intent broadcast that we have tried to start, but are
572 * waiting for its application's process to be created. We only
573 * need one (instead of a list) because we always process broadcasts
574 * one at a time, so no others can be started while waiting for this
575 * one.
576 */
577 BroadcastRecord mPendingBroadcast = null;
578
579 /**
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700580 * The receiver index that is pending, to restart the broadcast if needed.
581 */
582 int mPendingBroadcastRecvIndex;
583
584 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800585 * Keeps track of all IIntentReceivers that have been registered for
586 * broadcasts. Hash keys are the receiver IBinder, hash value is
587 * a ReceiverList.
588 */
589 final HashMap mRegisteredReceivers = new HashMap();
590
591 /**
592 * Resolver for broadcast intents to registered receivers.
593 * Holds BroadcastFilter (subclass of IntentFilter).
594 */
595 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
596 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
597 @Override
598 protected boolean allowFilterResult(
599 BroadcastFilter filter, List<BroadcastFilter> dest) {
600 IBinder target = filter.receiverList.receiver.asBinder();
601 for (int i=dest.size()-1; i>=0; i--) {
602 if (dest.get(i).receiverList.receiver.asBinder() == target) {
603 return false;
604 }
605 }
606 return true;
607 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -0700608
609 @Override
610 protected String packageForFilter(BroadcastFilter filter) {
611 return filter.packageName;
612 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800613 };
614
615 /**
616 * State of all active sticky broadcasts. Keys are the action of the
617 * sticky Intent, values are an ArrayList of all broadcasted intents with
618 * that action (which should usually be one).
619 */
620 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
621 new HashMap<String, ArrayList<Intent>>();
622
623 /**
624 * All currently running services.
625 */
626 final HashMap<ComponentName, ServiceRecord> mServices =
627 new HashMap<ComponentName, ServiceRecord>();
628
629 /**
630 * All currently running services indexed by the Intent used to start them.
631 */
632 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
633 new HashMap<Intent.FilterComparison, ServiceRecord>();
634
635 /**
636 * All currently bound service connections. Keys are the IBinder of
637 * the client's IServiceConnection.
638 */
Dianne Hackborn43d9ac82010-08-25 15:06:25 -0700639 final HashMap<IBinder, ArrayList<ConnectionRecord>> mServiceConnections
640 = new HashMap<IBinder, ArrayList<ConnectionRecord>>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800641
642 /**
643 * List of services that we have been asked to start,
644 * but haven't yet been able to. It is used to hold start requests
645 * while waiting for their corresponding application thread to get
646 * going.
647 */
648 final ArrayList<ServiceRecord> mPendingServices
649 = new ArrayList<ServiceRecord>();
650
651 /**
652 * List of services that are scheduled to restart following a crash.
653 */
654 final ArrayList<ServiceRecord> mRestartingServices
655 = new ArrayList<ServiceRecord>();
656
657 /**
658 * List of services that are in the process of being stopped.
659 */
660 final ArrayList<ServiceRecord> mStoppingServices
661 = new ArrayList<ServiceRecord>();
662
663 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700664 * Backup/restore process management
665 */
666 String mBackupAppName = null;
667 BackupRecord mBackupTarget = null;
668
669 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800670 * List of PendingThumbnailsRecord objects of clients who are still
671 * waiting to receive all of the thumbnails for a task.
672 */
673 final ArrayList mPendingThumbnails = new ArrayList();
674
675 /**
676 * List of HistoryRecord objects that have been finished and must
677 * still report back to a pending thumbnail receiver.
678 */
679 final ArrayList mCancelledThumbnails = new ArrayList();
680
681 /**
682 * All of the currently running global content providers. Keys are a
683 * string containing the provider name and values are a
684 * ContentProviderRecord object containing the data about it. Note
685 * that a single provider may be published under multiple names, so
686 * there may be multiple entries here for a single one in mProvidersByClass.
687 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700688 final HashMap<String, ContentProviderRecord> mProvidersByName
689 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800690
691 /**
692 * All of the currently running global content providers. Keys are a
693 * string containing the provider's implementation class and values are a
694 * ContentProviderRecord object containing the data about it.
695 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700696 final HashMap<String, ContentProviderRecord> mProvidersByClass
697 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800698
699 /**
700 * List of content providers who have clients waiting for them. The
701 * application is currently being launched and the provider will be
702 * removed from this list once it is published.
703 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700704 final ArrayList<ContentProviderRecord> mLaunchingProviders
705 = new ArrayList<ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800706
707 /**
708 * Global set of specific Uri permissions that have been granted.
709 */
710 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
711 = new SparseArray<HashMap<Uri, UriPermission>>();
712
Svetoslav Ganov54d068e2011-03-02 12:58:40 -0800713 CoreSettingsObserver mCoreSettingsObserver;
714
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800715 /**
716 * Thread-local storage used to carry caller permissions over through
717 * indirect content-provider access.
718 * @see #ActivityManagerService.openContentUri()
719 */
720 private class Identity {
721 public int pid;
722 public int uid;
723
724 Identity(int _pid, int _uid) {
725 pid = _pid;
726 uid = _uid;
727 }
728 }
729 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
730
731 /**
732 * All information we have collected about the runtime performance of
733 * any user id that can impact battery performance.
734 */
735 final BatteryStatsService mBatteryStatsService;
736
737 /**
738 * information about component usage
739 */
740 final UsageStatsService mUsageStatsService;
741
742 /**
743 * Current configuration information. HistoryRecord objects are given
744 * a reference to this object to indicate which configuration they are
745 * currently running in, so this object must be kept immutable.
746 */
747 Configuration mConfiguration = new Configuration();
748
749 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800750 * Current sequencing integer of the configuration, for skipping old
751 * configurations.
752 */
753 int mConfigurationSeq = 0;
754
755 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700756 * Hardware-reported OpenGLES version.
757 */
758 final int GL_ES_VERSION;
759
760 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800761 * List of initialization arguments to pass to all processes when binding applications to them.
762 * For example, references to the commonly used services.
763 */
764 HashMap<String, IBinder> mAppBindArgs;
765
766 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700767 * Temporary to avoid allocations. Protected by main lock.
768 */
769 final StringBuilder mStringBuilder = new StringBuilder(256);
770
771 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800772 * Used to control how we initialize the service.
773 */
774 boolean mStartRunning = false;
775 ComponentName mTopComponent;
776 String mTopAction;
777 String mTopData;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700778 boolean mProcessesReady = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800779 boolean mSystemReady = false;
780 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700781 boolean mWaitingUpdate = false;
782 boolean mDidUpdate = false;
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700783 boolean mOnBattery = false;
Dianne Hackborn0dad3642010-09-09 21:25:35 -0700784 boolean mLaunchWarningShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800785
786 Context mContext;
787
788 int mFactoryTest;
789
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700790 boolean mCheckedForSetup;
791
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800792 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700793 * The time at which we will allow normal application switches again,
794 * after a call to {@link #stopAppSwitches()}.
795 */
796 long mAppSwitchesAllowedTime;
797
798 /**
799 * This is set to true after the first switch after mAppSwitchesAllowedTime
800 * is set; any switches after that will clear the time.
801 */
802 boolean mDidAppSwitch;
803
804 /**
Dianne Hackborn287952c2010-09-22 22:34:31 -0700805 * Last time (in realtime) at which we checked for power usage.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700806 */
Dianne Hackborn287952c2010-09-22 22:34:31 -0700807 long mLastPowerCheckRealtime;
808
809 /**
810 * Last time (in uptime) at which we checked for power usage.
811 */
812 long mLastPowerCheckUptime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700813
814 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800815 * Set while we are wanting to sleep, to prevent any
816 * activities from being started/resumed.
817 */
818 boolean mSleeping = false;
819
820 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700821 * Set if we are shutting down the system, similar to sleeping.
822 */
823 boolean mShuttingDown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800824
825 /**
826 * Task identifier that activities are currently being started
827 * in. Incremented each time a new task is created.
828 * todo: Replace this with a TokenSpace class that generates non-repeating
829 * integers that won't wrap.
830 */
831 int mCurTask = 1;
832
833 /**
834 * Current sequence id for oom_adj computation traversal.
835 */
836 int mAdjSeq = 0;
837
838 /**
Dianne Hackborn906497c2010-05-10 15:57:38 -0700839 * Current sequence id for process LRU updating.
840 */
841 int mLruSeq = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800842
843 /**
844 * System monitoring: number of processes that died since the last
845 * N procs were started.
846 */
847 int[] mProcDeaths = new int[20];
848
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700849 /**
850 * This is set if we had to do a delayed dexopt of an app before launching
851 * it, to increasing the ANR timeouts in that case.
852 */
853 boolean mDidDexOpt;
854
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800855 String mDebugApp = null;
856 boolean mWaitForDebugger = false;
857 boolean mDebugTransient = false;
858 String mOrigDebugApp = null;
859 boolean mOrigWaitForDebugger = false;
860 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700861 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800862
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700863 final RemoteCallbackList<IActivityWatcher> mWatchers
864 = new RemoteCallbackList<IActivityWatcher>();
Jeff Sharkeya4620792011-05-20 15:29:23 -0700865
866 final RemoteCallbackList<IProcessObserver> mProcessObservers
867 = new RemoteCallbackList<IProcessObserver>();
868
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800869 /**
870 * Callback of last caller to {@link #requestPss}.
871 */
872 Runnable mRequestPssCallback;
873
874 /**
875 * Remaining processes for which we are waiting results from the last
876 * call to {@link #requestPss}.
877 */
878 final ArrayList<ProcessRecord> mRequestPssList
879 = new ArrayList<ProcessRecord>();
880
881 /**
882 * Runtime statistics collection thread. This object's lock is used to
883 * protect all related state.
884 */
885 final Thread mProcessStatsThread;
886
887 /**
888 * Used to collect process stats when showing not responding dialog.
889 * Protected by mProcessStatsThread.
890 */
891 final ProcessStats mProcessStats = new ProcessStats(
892 MONITOR_THREAD_CPU_USAGE);
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700893 final AtomicLong mLastCpuTime = new AtomicLong(0);
894 final AtomicBoolean mProcessStatsMutexFree = new AtomicBoolean(true);
895
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800896 long mLastWriteTime = 0;
897
898 /**
899 * Set to true after the system has finished booting.
900 */
901 boolean mBooted = false;
902
Dianne Hackbornce86ba82011-07-13 19:33:41 -0700903 int mProcessLimit = MAX_HIDDEN_APPS;
904 int mProcessLimitOverride = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800905
906 WindowManagerService mWindowManager;
907
908 static ActivityManagerService mSelf;
909 static ActivityThread mSystemThread;
910
911 private final class AppDeathRecipient implements IBinder.DeathRecipient {
912 final ProcessRecord mApp;
913 final int mPid;
914 final IApplicationThread mAppThread;
915
916 AppDeathRecipient(ProcessRecord app, int pid,
917 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800918 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800919 TAG, "New death recipient " + this
920 + " for thread " + thread.asBinder());
921 mApp = app;
922 mPid = pid;
923 mAppThread = thread;
924 }
925
926 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800927 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800928 TAG, "Death received in " + this
929 + " for thread " + mAppThread.asBinder());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800930 synchronized(ActivityManagerService.this) {
931 appDiedLocked(mApp, mPid, mAppThread);
932 }
933 }
934 }
935
936 static final int SHOW_ERROR_MSG = 1;
937 static final int SHOW_NOT_RESPONDING_MSG = 2;
938 static final int SHOW_FACTORY_ERROR_MSG = 3;
939 static final int UPDATE_CONFIGURATION_MSG = 4;
940 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
941 static final int WAIT_FOR_DEBUGGER_MSG = 6;
942 static final int BROADCAST_INTENT_MSG = 7;
943 static final int BROADCAST_TIMEOUT_MSG = 8;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800944 static final int SERVICE_TIMEOUT_MSG = 12;
945 static final int UPDATE_TIME_ZONE = 13;
946 static final int SHOW_UID_ERROR_MSG = 14;
947 static final int IM_FEELING_LUCKY_MSG = 15;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800948 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700949 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -0700950 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800951 static final int FINALIZE_PENDING_INTENT_MSG = 23;
Dianne Hackborn860755f2010-06-03 18:47:52 -0700952 static final int POST_HEAVY_NOTIFICATION_MSG = 24;
953 static final int CANCEL_HEAVY_NOTIFICATION_MSG = 25;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700954 static final int SHOW_STRICT_MODE_VIOLATION_MSG = 26;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700955 static final int CHECK_EXCESSIVE_WAKE_LOCKS_MSG = 27;
Robert Greenwalt03595d02010-11-02 14:08:23 -0700956 static final int CLEAR_DNS_CACHE = 28;
Robert Greenwalt434203a2010-10-11 16:00:27 -0700957 static final int UPDATE_HTTP_PROXY = 29;
Dianne Hackborn36cd41f2011-05-25 21:00:46 -0700958 static final int SHOW_COMPAT_MODE_DIALOG_MSG = 30;
Dianne Hackborn36f80f32011-05-31 18:26:45 -0700959 static final int DISPATCH_FOREGROUND_ACTIVITIES_CHANGED = 31;
960 static final int DISPATCH_PROCESS_DIED = 32;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800961
962 AlertDialog mUidAlert;
Dianne Hackborn36cd41f2011-05-25 21:00:46 -0700963 CompatModeDialog mCompatModeDialog;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800964
965 final Handler mHandler = new Handler() {
966 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800967 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800968 //}
969
970 public void handleMessage(Message msg) {
971 switch (msg.what) {
972 case SHOW_ERROR_MSG: {
973 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800974 synchronized (ActivityManagerService.this) {
975 ProcessRecord proc = (ProcessRecord)data.get("app");
976 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800977 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800978 return;
979 }
980 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -0700981 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -0800982 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800983 d.show();
984 proc.crashDialog = d;
985 } else {
986 // The device is asleep, so just pretend that the user
987 // saw a crash dialog and hit "force quit".
988 res.set(0);
989 }
990 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700991
992 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800993 } break;
994 case SHOW_NOT_RESPONDING_MSG: {
995 synchronized (ActivityManagerService.this) {
996 HashMap data = (HashMap) msg.obj;
997 ProcessRecord proc = (ProcessRecord)data.get("app");
998 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800999 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001000 return;
1001 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001002
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001003 Intent intent = new Intent("android.intent.action.ANR");
1004 if (!mProcessesReady) {
1005 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
1006 }
1007 broadcastIntentLocked(null, null, intent,
The Android Open Source Project4df24232009-03-05 14:34:35 -08001008 null, null, 0, null, null, null,
1009 false, false, MY_PID, Process.SYSTEM_UID);
1010
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001011 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001012 mContext, proc, (ActivityRecord)data.get("activity"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001013 d.show();
1014 proc.anrDialog = d;
1015 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001016
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001017 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001018 } break;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001019 case SHOW_STRICT_MODE_VIOLATION_MSG: {
1020 HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
1021 synchronized (ActivityManagerService.this) {
1022 ProcessRecord proc = (ProcessRecord) data.get("app");
1023 if (proc == null) {
1024 Slog.e(TAG, "App not found when showing strict mode dialog.");
1025 break;
1026 }
1027 if (proc.crashDialog != null) {
1028 Slog.e(TAG, "App already has strict mode dialog: " + proc);
1029 return;
1030 }
1031 AppErrorResult res = (AppErrorResult) data.get("result");
1032 if (!mSleeping && !mShuttingDown) {
1033 Dialog d = new StrictModeViolationDialog(mContext, res, proc);
1034 d.show();
1035 proc.crashDialog = d;
1036 } else {
1037 // The device is asleep, so just pretend that the user
1038 // saw a crash dialog and hit "force quit".
1039 res.set(0);
1040 }
1041 }
1042 ensureBootCompleted();
1043 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001044 case SHOW_FACTORY_ERROR_MSG: {
1045 Dialog d = new FactoryErrorDialog(
1046 mContext, msg.getData().getCharSequence("msg"));
1047 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001048 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001049 } break;
1050 case UPDATE_CONFIGURATION_MSG: {
1051 final ContentResolver resolver = mContext.getContentResolver();
1052 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1053 } break;
1054 case GC_BACKGROUND_PROCESSES_MSG: {
1055 synchronized (ActivityManagerService.this) {
1056 performAppGcsIfAppropriateLocked();
1057 }
1058 } break;
1059 case WAIT_FOR_DEBUGGER_MSG: {
1060 synchronized (ActivityManagerService.this) {
1061 ProcessRecord app = (ProcessRecord)msg.obj;
1062 if (msg.arg1 != 0) {
1063 if (!app.waitedForDebugger) {
1064 Dialog d = new AppWaitingForDebuggerDialog(
1065 ActivityManagerService.this,
1066 mContext, app);
1067 app.waitDialog = d;
1068 app.waitedForDebugger = true;
1069 d.show();
1070 }
1071 } else {
1072 if (app.waitDialog != null) {
1073 app.waitDialog.dismiss();
1074 app.waitDialog = null;
1075 }
1076 }
1077 }
1078 } break;
1079 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001080 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001081 TAG, "Received BROADCAST_INTENT_MSG");
1082 processNextBroadcast(true);
1083 } break;
1084 case BROADCAST_TIMEOUT_MSG: {
Jeff Brown4d94a762010-09-23 11:33:28 -07001085 synchronized (ActivityManagerService.this) {
1086 broadcastTimeoutLocked(true);
Jeff Hamiltonacf84742010-05-25 22:10:18 -05001087 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001088 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001089 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001090 if (mDidDexOpt) {
1091 mDidDexOpt = false;
1092 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1093 nmsg.obj = msg.obj;
1094 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1095 return;
1096 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001097 serviceTimeout((ProcessRecord)msg.obj);
1098 } break;
1099 case UPDATE_TIME_ZONE: {
1100 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001101 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1102 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001103 if (r.thread != null) {
1104 try {
1105 r.thread.updateTimeZone();
1106 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001107 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001108 }
1109 }
1110 }
1111 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001112 } break;
Robert Greenwalt03595d02010-11-02 14:08:23 -07001113 case CLEAR_DNS_CACHE: {
1114 synchronized (ActivityManagerService.this) {
1115 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1116 ProcessRecord r = mLruProcesses.get(i);
1117 if (r.thread != null) {
1118 try {
1119 r.thread.clearDnsCache();
1120 } catch (RemoteException ex) {
1121 Slog.w(TAG, "Failed to clear dns cache for: " + r.info.processName);
1122 }
1123 }
1124 }
1125 }
1126 } break;
Robert Greenwalt434203a2010-10-11 16:00:27 -07001127 case UPDATE_HTTP_PROXY: {
1128 ProxyProperties proxy = (ProxyProperties)msg.obj;
1129 String host = "";
1130 String port = "";
1131 String exclList = "";
1132 if (proxy != null) {
1133 host = proxy.getHost();
1134 port = Integer.toString(proxy.getPort());
1135 exclList = proxy.getExclusionList();
1136 }
1137 synchronized (ActivityManagerService.this) {
1138 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1139 ProcessRecord r = mLruProcesses.get(i);
1140 if (r.thread != null) {
1141 try {
1142 r.thread.setHttpProxy(host, port, exclList);
1143 } catch (RemoteException ex) {
1144 Slog.w(TAG, "Failed to update http proxy for: " +
1145 r.info.processName);
1146 }
1147 }
1148 }
1149 }
1150 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001151 case SHOW_UID_ERROR_MSG: {
1152 // XXX This is a temporary dialog, no need to localize.
1153 AlertDialog d = new BaseErrorDialog(mContext);
1154 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1155 d.setCancelable(false);
1156 d.setTitle("System UIDs Inconsistent");
1157 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 +02001158 d.setButton(DialogInterface.BUTTON_POSITIVE, "I'm Feeling Lucky",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001159 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1160 mUidAlert = d;
1161 d.show();
1162 } break;
1163 case IM_FEELING_LUCKY_MSG: {
1164 if (mUidAlert != null) {
1165 mUidAlert.dismiss();
1166 mUidAlert = null;
1167 }
1168 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001169 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001170 if (mDidDexOpt) {
1171 mDidDexOpt = false;
1172 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1173 nmsg.obj = msg.obj;
1174 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1175 return;
1176 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001177 ProcessRecord app = (ProcessRecord)msg.obj;
1178 synchronized (ActivityManagerService.this) {
1179 processStartTimedOutLocked(app);
1180 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001181 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001182 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1183 synchronized (ActivityManagerService.this) {
1184 doPendingActivityLaunchesLocked(true);
1185 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001186 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001187 case KILL_APPLICATION_MSG: {
1188 synchronized (ActivityManagerService.this) {
1189 int uid = msg.arg1;
1190 boolean restart = (msg.arg2 == 1);
1191 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001192 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001193 }
1194 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001195 case FINALIZE_PENDING_INTENT_MSG: {
1196 ((PendingIntentRecord)msg.obj).completeFinalize();
1197 } break;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001198 case POST_HEAVY_NOTIFICATION_MSG: {
1199 INotificationManager inm = NotificationManager.getService();
1200 if (inm == null) {
1201 return;
1202 }
1203
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001204 ActivityRecord root = (ActivityRecord)msg.obj;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001205 ProcessRecord process = root.app;
1206 if (process == null) {
1207 return;
1208 }
1209
1210 try {
1211 Context context = mContext.createPackageContext(process.info.packageName, 0);
1212 String text = mContext.getString(R.string.heavy_weight_notification,
1213 context.getApplicationInfo().loadLabel(context.getPackageManager()));
1214 Notification notification = new Notification();
1215 notification.icon = com.android.internal.R.drawable.stat_sys_adb; //context.getApplicationInfo().icon;
1216 notification.when = 0;
1217 notification.flags = Notification.FLAG_ONGOING_EVENT;
1218 notification.tickerText = text;
1219 notification.defaults = 0; // please be quiet
1220 notification.sound = null;
1221 notification.vibrate = null;
1222 notification.setLatestEventInfo(context, text,
1223 mContext.getText(R.string.heavy_weight_notification_detail),
1224 PendingIntent.getActivity(mContext, 0, root.intent,
1225 PendingIntent.FLAG_CANCEL_CURRENT));
1226
1227 try {
1228 int[] outId = new int[1];
1229 inm.enqueueNotification("android", R.string.heavy_weight_notification,
1230 notification, outId);
1231 } catch (RuntimeException e) {
1232 Slog.w(ActivityManagerService.TAG,
1233 "Error showing notification for heavy-weight app", e);
1234 } catch (RemoteException e) {
1235 }
1236 } catch (NameNotFoundException e) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07001237 Slog.w(TAG, "Unable to create context for heavy notification", e);
Dianne Hackborn860755f2010-06-03 18:47:52 -07001238 }
1239 } break;
1240 case CANCEL_HEAVY_NOTIFICATION_MSG: {
1241 INotificationManager inm = NotificationManager.getService();
1242 if (inm == null) {
1243 return;
1244 }
1245 try {
1246 inm.cancelNotification("android",
1247 R.string.heavy_weight_notification);
1248 } catch (RuntimeException e) {
1249 Slog.w(ActivityManagerService.TAG,
1250 "Error canceling notification for service", e);
1251 } catch (RemoteException e) {
1252 }
1253 } break;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001254 case CHECK_EXCESSIVE_WAKE_LOCKS_MSG: {
1255 synchronized (ActivityManagerService.this) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001256 checkExcessivePowerUsageLocked(true);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -07001257 removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001258 Message nmsg = obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
1259 sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001260 }
1261 } break;
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07001262 case SHOW_COMPAT_MODE_DIALOG_MSG: {
1263 synchronized (ActivityManagerService.this) {
1264 ActivityRecord ar = (ActivityRecord)msg.obj;
1265 if (mCompatModeDialog != null) {
1266 if (mCompatModeDialog.mAppInfo.packageName.equals(
1267 ar.info.applicationInfo.packageName)) {
1268 return;
1269 }
1270 mCompatModeDialog.dismiss();
1271 mCompatModeDialog = null;
1272 }
Dianne Hackborn29478262011-06-07 15:44:22 -07001273 if (ar != null && false) {
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07001274 if (mCompatModePackages.getPackageAskCompatModeLocked(
1275 ar.packageName)) {
1276 int mode = mCompatModePackages.computeCompatModeLocked(
1277 ar.info.applicationInfo);
1278 if (mode == ActivityManager.COMPAT_MODE_DISABLED
1279 || mode == ActivityManager.COMPAT_MODE_ENABLED) {
1280 mCompatModeDialog = new CompatModeDialog(
1281 ActivityManagerService.this, mContext,
1282 ar.info.applicationInfo);
1283 mCompatModeDialog.show();
1284 }
1285 }
1286 }
1287 }
Dianne Hackborn36f80f32011-05-31 18:26:45 -07001288 break;
1289 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07001290 case DISPATCH_FOREGROUND_ACTIVITIES_CHANGED: {
Jeff Sharkey287bd832011-05-28 19:36:26 -07001291 final int pid = msg.arg1;
1292 final int uid = msg.arg2;
1293 final boolean foregroundActivities = (Boolean) msg.obj;
1294 dispatchForegroundActivitiesChanged(pid, uid, foregroundActivities);
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07001295 break;
1296 }
1297 case DISPATCH_PROCESS_DIED: {
Jeff Sharkey287bd832011-05-28 19:36:26 -07001298 final int pid = msg.arg1;
1299 final int uid = msg.arg2;
1300 dispatchProcessDied(pid, uid);
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07001301 break;
1302 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001303 }
1304 }
1305 };
1306
1307 public static void setSystemProcess() {
1308 try {
1309 ActivityManagerService m = mSelf;
1310
1311 ServiceManager.addService("activity", m);
1312 ServiceManager.addService("meminfo", new MemBinder(m));
Chet Haase9c1e23b2011-03-24 10:51:31 -07001313 ServiceManager.addService("gfxinfo", new GraphicsBinder(m));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001314 if (MONITOR_CPU_USAGE) {
1315 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1316 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001317 ServiceManager.addService("permission", new PermissionController(m));
1318
1319 ApplicationInfo info =
1320 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001321 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001322 mSystemThread.installSystemApplicationInfo(info);
1323
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001324 synchronized (mSelf) {
1325 ProcessRecord app = mSelf.newProcessRecordLocked(
1326 mSystemThread.getApplicationThread(), info,
1327 info.processName);
1328 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001329 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001330 app.maxAdj = SYSTEM_ADJ;
1331 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1332 synchronized (mSelf.mPidsSelfLocked) {
1333 mSelf.mPidsSelfLocked.put(app.pid, app);
1334 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001335 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001336 }
1337 } catch (PackageManager.NameNotFoundException e) {
1338 throw new RuntimeException(
1339 "Unable to find android system package", e);
1340 }
1341 }
1342
1343 public void setWindowManager(WindowManagerService wm) {
1344 mWindowManager = wm;
1345 }
1346
1347 public static final Context main(int factoryTest) {
1348 AThread thr = new AThread();
1349 thr.start();
1350
1351 synchronized (thr) {
1352 while (thr.mService == null) {
1353 try {
1354 thr.wait();
1355 } catch (InterruptedException e) {
1356 }
1357 }
1358 }
1359
1360 ActivityManagerService m = thr.mService;
1361 mSelf = m;
1362 ActivityThread at = ActivityThread.systemMain();
1363 mSystemThread = at;
1364 Context context = at.getSystemContext();
Dianne Hackborn247fe742011-01-08 17:25:57 -08001365 context.setTheme(android.R.style.Theme_Holo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001366 m.mContext = context;
1367 m.mFactoryTest = factoryTest;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001368 m.mMainStack = new ActivityStack(m, context, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001369
1370 m.mBatteryStatsService.publish(context);
1371 m.mUsageStatsService.publish(context);
1372
1373 synchronized (thr) {
1374 thr.mReady = true;
1375 thr.notifyAll();
1376 }
1377
1378 m.startRunning(null, null, null, null);
1379
1380 return context;
1381 }
1382
1383 public static ActivityManagerService self() {
1384 return mSelf;
1385 }
1386
1387 static class AThread extends Thread {
1388 ActivityManagerService mService;
1389 boolean mReady = false;
1390
1391 public AThread() {
1392 super("ActivityManager");
1393 }
1394
1395 public void run() {
1396 Looper.prepare();
1397
1398 android.os.Process.setThreadPriority(
1399 android.os.Process.THREAD_PRIORITY_FOREGROUND);
Christopher Tate160edb32010-06-30 17:46:30 -07001400 android.os.Process.setCanSelfBackground(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001401
1402 ActivityManagerService m = new ActivityManagerService();
1403
1404 synchronized (this) {
1405 mService = m;
1406 notifyAll();
1407 }
1408
1409 synchronized (this) {
1410 while (!mReady) {
1411 try {
1412 wait();
1413 } catch (InterruptedException e) {
1414 }
1415 }
1416 }
1417
Brad Fitzpatrickec062f62010-11-03 09:56:54 -07001418 // For debug builds, log event loop stalls to dropbox for analysis.
1419 if (StrictMode.conditionallyEnableDebugLogging()) {
1420 Slog.i(TAG, "Enabled StrictMode logging for AThread's Looper");
1421 }
1422
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001423 Looper.loop();
1424 }
1425 }
1426
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001427 static class MemBinder extends Binder {
1428 ActivityManagerService mActivityManagerService;
1429 MemBinder(ActivityManagerService activityManagerService) {
1430 mActivityManagerService = activityManagerService;
1431 }
1432
1433 @Override
1434 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07001435 mActivityManagerService.dumpApplicationMemoryUsage(fd, pw, " ", args);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001436 }
1437 }
1438
Chet Haase9c1e23b2011-03-24 10:51:31 -07001439 static class GraphicsBinder extends Binder {
1440 ActivityManagerService mActivityManagerService;
1441 GraphicsBinder(ActivityManagerService activityManagerService) {
1442 mActivityManagerService = activityManagerService;
1443 }
1444
1445 @Override
1446 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07001447 mActivityManagerService.dumpGraphicsHardwareUsage(fd, pw, args);
Chet Haase9c1e23b2011-03-24 10:51:31 -07001448 }
1449 }
1450
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001451 static class CpuBinder extends Binder {
1452 ActivityManagerService mActivityManagerService;
1453 CpuBinder(ActivityManagerService activityManagerService) {
1454 mActivityManagerService = activityManagerService;
1455 }
1456
1457 @Override
1458 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1459 synchronized (mActivityManagerService.mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07001460 pw.print(mActivityManagerService.mProcessStats.printCurrentLoad());
1461 pw.print(mActivityManagerService.mProcessStats.printCurrentState(
1462 SystemClock.uptimeMillis()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001463 }
1464 }
1465 }
1466
1467 private ActivityManagerService() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001468 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001469
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001470 File dataDir = Environment.getDataDirectory();
1471 File systemDir = new File(dataDir, "system");
1472 systemDir.mkdirs();
1473 mBatteryStatsService = new BatteryStatsService(new File(
1474 systemDir, "batterystats.bin").toString());
1475 mBatteryStatsService.getActiveStatistics().readLocked();
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001476 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
Dianne Hackborn287952c2010-09-22 22:34:31 -07001477 mOnBattery = DEBUG_POWER ? true
1478 : mBatteryStatsService.getActiveStatistics().getIsOnBattery();
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001479 mBatteryStatsService.getActiveStatistics().setCallback(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001480
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001481 mUsageStatsService = new UsageStatsService(new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001482 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001483
Jack Palevichb90d28c2009-07-22 15:35:24 -07001484 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1485 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1486
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001487 mConfiguration.setToDefaults();
1488 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001489 mProcessStats.init();
1490
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07001491 mCompatModePackages = new CompatModePackages(this, systemDir);
1492
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001493 // Add ourself to the Watchdog monitors.
1494 Watchdog.getInstance().addMonitor(this);
1495
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001496 mProcessStatsThread = new Thread("ProcessStats") {
1497 public void run() {
1498 while (true) {
1499 try {
1500 try {
1501 synchronized(this) {
1502 final long now = SystemClock.uptimeMillis();
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001503 long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001504 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001505 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001506 // + ", write delay=" + nextWriteDelay);
1507 if (nextWriteDelay < nextCpuDelay) {
1508 nextCpuDelay = nextWriteDelay;
1509 }
1510 if (nextCpuDelay > 0) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001511 mProcessStatsMutexFree.set(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001512 this.wait(nextCpuDelay);
1513 }
1514 }
1515 } catch (InterruptedException e) {
1516 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001517 updateCpuStatsNow();
1518 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001519 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001520 }
1521 }
1522 }
1523 };
1524 mProcessStatsThread.start();
1525 }
1526
1527 @Override
1528 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1529 throws RemoteException {
1530 try {
1531 return super.onTransact(code, data, reply, flags);
1532 } catch (RuntimeException e) {
1533 // The activity manager only throws security exceptions, so let's
1534 // log all others.
1535 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001536 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001537 }
1538 throw e;
1539 }
1540 }
1541
1542 void updateCpuStats() {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001543 final long now = SystemClock.uptimeMillis();
1544 if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
1545 return;
1546 }
1547 if (mProcessStatsMutexFree.compareAndSet(true, false)) {
1548 synchronized (mProcessStatsThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001549 mProcessStatsThread.notify();
1550 }
1551 }
1552 }
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001553
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001554 void updateCpuStatsNow() {
1555 synchronized (mProcessStatsThread) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001556 mProcessStatsMutexFree.set(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001557 final long now = SystemClock.uptimeMillis();
1558 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001559
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001560 if (MONITOR_CPU_USAGE &&
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001561 mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
1562 mLastCpuTime.set(now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001563 haveNewCpuStats = true;
1564 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001565 //Slog.i(TAG, mProcessStats.printCurrentState());
1566 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001567 // + mProcessStats.getTotalCpuPercent() + "%");
1568
Joe Onorato8a9b2202010-02-26 18:56:32 -08001569 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001570 if ("true".equals(SystemProperties.get("events.cpu"))) {
1571 int user = mProcessStats.getLastUserTime();
1572 int system = mProcessStats.getLastSystemTime();
1573 int iowait = mProcessStats.getLastIoWaitTime();
1574 int irq = mProcessStats.getLastIrqTime();
1575 int softIrq = mProcessStats.getLastSoftIrqTime();
1576 int idle = mProcessStats.getLastIdleTime();
1577
1578 int total = user + system + iowait + irq + softIrq + idle;
1579 if (total == 0) total = 1;
1580
Doug Zongker2bec3d42009-12-04 12:52:44 -08001581 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001582 ((user+system+iowait+irq+softIrq) * 100) / total,
1583 (user * 100) / total,
1584 (system * 100) / total,
1585 (iowait * 100) / total,
1586 (irq * 100) / total,
1587 (softIrq * 100) / total);
1588 }
1589 }
1590
Amith Yamasanie43530a2009-08-21 13:11:37 -07001591 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001592 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001593 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001594 synchronized(mPidsSelfLocked) {
1595 if (haveNewCpuStats) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001596 if (mOnBattery) {
1597 int perc = bstats.startAddingCpuLocked();
1598 int totalUTime = 0;
1599 int totalSTime = 0;
Dianne Hackborn287952c2010-09-22 22:34:31 -07001600 final int N = mProcessStats.countStats();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001601 for (int i=0; i<N; i++) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001602 ProcessStats.Stats st = mProcessStats.getStats(i);
1603 if (!st.working) {
1604 continue;
1605 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001606 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001607 int otherUTime = (st.rel_utime*perc)/100;
1608 int otherSTime = (st.rel_stime*perc)/100;
1609 totalUTime += otherUTime;
1610 totalSTime += otherSTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001611 if (pr != null) {
1612 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001613 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1614 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001615 ps.addSpeedStepTimes(cpuSpeedTimes);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001616 pr.curCpuTime += (st.rel_utime+st.rel_stime) * 10;
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001617 } else {
1618 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001619 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001620 if (ps != null) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001621 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1622 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001623 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001624 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001625 }
1626 }
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001627 bstats.finishAddingCpuLocked(perc, totalUTime,
1628 totalSTime, cpuSpeedTimes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001629 }
1630 }
1631 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001632
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001633 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1634 mLastWriteTime = now;
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001635 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001636 }
1637 }
1638 }
1639 }
1640
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001641 @Override
1642 public void batteryNeedsCpuUpdate() {
1643 updateCpuStatsNow();
1644 }
1645
1646 @Override
1647 public void batteryPowerChanged(boolean onBattery) {
1648 // When plugging in, update the CPU stats first before changing
1649 // the plug state.
1650 updateCpuStatsNow();
1651 synchronized (this) {
1652 synchronized(mPidsSelfLocked) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001653 mOnBattery = DEBUG_POWER ? true : onBattery;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001654 }
1655 }
1656 }
1657
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001658 /**
1659 * Initialize the application bind args. These are passed to each
1660 * process when the bindApplication() IPC is sent to the process. They're
1661 * lazily setup to make sure the services are running when they're asked for.
1662 */
1663 private HashMap<String, IBinder> getCommonServicesLocked() {
1664 if (mAppBindArgs == null) {
1665 mAppBindArgs = new HashMap<String, IBinder>();
1666
1667 // Setup the application init args
1668 mAppBindArgs.put("package", ServiceManager.getService("package"));
1669 mAppBindArgs.put("window", ServiceManager.getService("window"));
1670 mAppBindArgs.put(Context.ALARM_SERVICE,
1671 ServiceManager.getService(Context.ALARM_SERVICE));
1672 }
1673 return mAppBindArgs;
1674 }
1675
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001676 final void setFocusedActivityLocked(ActivityRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001677 if (mFocusedActivity != r) {
1678 mFocusedActivity = r;
1679 mWindowManager.setFocusedApp(r, true);
1680 }
1681 }
1682
Dianne Hackborn906497c2010-05-10 15:57:38 -07001683 private final void updateLruProcessInternalLocked(ProcessRecord app,
1684 boolean oomAdj, boolean updateActivityTime, int bestPos) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001685 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001686 int lrui = mLruProcesses.indexOf(app);
1687 if (lrui >= 0) mLruProcesses.remove(lrui);
1688
1689 int i = mLruProcesses.size()-1;
1690 int skipTop = 0;
1691
Dianne Hackborn906497c2010-05-10 15:57:38 -07001692 app.lruSeq = mLruSeq;
1693
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001694 // compute the new weight for this process.
1695 if (updateActivityTime) {
1696 app.lastActivityTime = SystemClock.uptimeMillis();
1697 }
1698 if (app.activities.size() > 0) {
1699 // If this process has activities, we more strongly want to keep
1700 // it around.
1701 app.lruWeight = app.lastActivityTime;
1702 } else if (app.pubProviders.size() > 0) {
1703 // If this process contains content providers, we want to keep
1704 // it a little more strongly.
1705 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1706 // Also don't let it kick out the first few "real" hidden processes.
1707 skipTop = MIN_HIDDEN_APPS;
1708 } else {
1709 // If this process doesn't have activities, we less strongly
1710 // want to keep it around, and generally want to avoid getting
1711 // in front of any very recently used activities.
1712 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1713 // Also don't let it kick out the first few "real" hidden processes.
1714 skipTop = MIN_HIDDEN_APPS;
1715 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001716
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001717 while (i >= 0) {
1718 ProcessRecord p = mLruProcesses.get(i);
1719 // If this app shouldn't be in front of the first N background
1720 // apps, then skip over that many that are currently hidden.
1721 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1722 skipTop--;
1723 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001724 if (p.lruWeight <= app.lruWeight || i < bestPos) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001725 mLruProcesses.add(i+1, app);
1726 break;
1727 }
1728 i--;
1729 }
1730 if (i < 0) {
1731 mLruProcesses.add(0, app);
1732 }
1733
Dianne Hackborn906497c2010-05-10 15:57:38 -07001734 // If the app is currently using a content provider or service,
1735 // bump those processes as well.
1736 if (app.connections.size() > 0) {
1737 for (ConnectionRecord cr : app.connections) {
1738 if (cr.binding != null && cr.binding.service != null
1739 && cr.binding.service.app != null
1740 && cr.binding.service.app.lruSeq != mLruSeq) {
1741 updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,
1742 updateActivityTime, i+1);
1743 }
1744 }
1745 }
1746 if (app.conProviders.size() > 0) {
1747 for (ContentProviderRecord cpr : app.conProviders.keySet()) {
1748 if (cpr.app != null && cpr.app.lruSeq != mLruSeq) {
1749 updateLruProcessInternalLocked(cpr.app, oomAdj,
1750 updateActivityTime, i+1);
1751 }
1752 }
1753 }
1754
Joe Onorato8a9b2202010-02-26 18:56:32 -08001755 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001756 if (oomAdj) {
1757 updateOomAdjLocked();
1758 }
1759 }
1760
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001761 final void updateLruProcessLocked(ProcessRecord app,
Dianne Hackborn906497c2010-05-10 15:57:38 -07001762 boolean oomAdj, boolean updateActivityTime) {
1763 mLruSeq++;
1764 updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
1765 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07001766
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001767 final ProcessRecord getProcessRecordLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001768 String processName, int uid) {
1769 if (uid == Process.SYSTEM_UID) {
1770 // The system gets to run in any process. If there are multiple
1771 // processes with the same uid, just pick the first (this
1772 // should never happen).
1773 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1774 processName);
1775 return procs != null ? procs.valueAt(0) : null;
1776 }
1777 ProcessRecord proc = mProcessNames.get(processName, uid);
1778 return proc;
1779 }
1780
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001781 void ensurePackageDexOpt(String packageName) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001782 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001783 try {
1784 if (pm.performDexOpt(packageName)) {
1785 mDidDexOpt = true;
1786 }
1787 } catch (RemoteException e) {
1788 }
1789 }
1790
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001791 boolean isNextTransitionForward() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001792 int transit = mWindowManager.getPendingAppTransition();
1793 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1794 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1795 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1796 }
1797
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001798 final ProcessRecord startProcessLocked(String processName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001799 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001800 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001801 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1802 // We don't have to do anything more if:
1803 // (1) There is an existing application record; and
1804 // (2) The caller doesn't think it is dead, OR there is no thread
1805 // object attached to it so we know it couldn't have crashed; and
1806 // (3) There is a pid assigned to it, so it is either starting or
1807 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001808 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001809 + " app=" + app + " knownToBeDead=" + knownToBeDead
1810 + " thread=" + (app != null ? app.thread : null)
1811 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01001812 if (app != null && app.pid > 0) {
1813 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001814 // We already have the app running, or are waiting for it to
1815 // come up (we have a pid but not yet its thread), so keep it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001816 if (DEBUG_PROCESSES) Slog.v(TAG, "App already running: " + app);
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001817 // If this is a new package in the process, add the package to the list
1818 app.addPackage(info.packageName);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001819 return app;
1820 } else {
1821 // An application record is attached to a previous process,
1822 // clean it up now.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001823 if (DEBUG_PROCESSES) Slog.v(TAG, "App died: " + app);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001824 handleAppDiedLocked(app, true);
1825 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001826 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01001827
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001828 String hostingNameStr = hostingName != null
1829 ? hostingName.flattenToShortString() : null;
1830
1831 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1832 // If we are in the background, then check to see if this process
1833 // is bad. If so, we will just silently fail.
1834 if (mBadProcesses.get(info.processName, info.uid) != null) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001835 if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid
1836 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001837 return null;
1838 }
1839 } else {
1840 // When the user is explicitly starting a process, then clear its
1841 // crash count so that we won't make it bad until they see at
1842 // least one crash dialog again, and make the process good again
1843 // if it had been bad.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001844 if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
1845 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001846 mProcessCrashTimes.remove(info.processName, info.uid);
1847 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001848 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001849 info.processName);
1850 mBadProcesses.remove(info.processName, info.uid);
1851 if (app != null) {
1852 app.bad = false;
1853 }
1854 }
1855 }
1856
1857 if (app == null) {
1858 app = newProcessRecordLocked(null, info, processName);
1859 mProcessNames.put(processName, info.uid, app);
1860 } else {
1861 // If this is a new package in the process, add the package to the list
1862 app.addPackage(info.packageName);
1863 }
1864
1865 // If the system is not ready yet, then hold off on starting this
1866 // process until it is.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001867 if (!mProcessesReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001868 && !isAllowedWhileBooting(info)
1869 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001870 if (!mProcessesOnHold.contains(app)) {
1871 mProcessesOnHold.add(app);
1872 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001873 if (DEBUG_PROCESSES) Slog.v(TAG, "System not ready, putting on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001874 return app;
1875 }
1876
1877 startProcessLocked(app, hostingType, hostingNameStr);
1878 return (app.pid != 0) ? app : null;
1879 }
1880
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001881 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1882 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1883 }
1884
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001885 private final void startProcessLocked(ProcessRecord app,
1886 String hostingType, String hostingNameStr) {
1887 if (app.pid > 0 && app.pid != MY_PID) {
1888 synchronized (mPidsSelfLocked) {
1889 mPidsSelfLocked.remove(app.pid);
1890 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1891 }
1892 app.pid = 0;
1893 }
1894
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001895 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
1896 "startProcessLocked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001897 mProcessesOnHold.remove(app);
1898
1899 updateCpuStats();
1900
1901 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1902 mProcDeaths[0] = 0;
1903
1904 try {
1905 int uid = app.info.uid;
1906 int[] gids = null;
1907 try {
1908 gids = mContext.getPackageManager().getPackageGids(
1909 app.info.packageName);
1910 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001911 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001912 }
1913 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1914 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1915 && mTopComponent != null
1916 && app.processName.equals(mTopComponent.getPackageName())) {
1917 uid = 0;
1918 }
1919 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1920 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1921 uid = 0;
1922 }
1923 }
1924 int debugFlags = 0;
1925 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1926 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
Elliott Hughesfa36aee2011-06-17 14:39:41 -07001927 // Also turn on CheckJNI for debuggable apps. It's quite
1928 // awkward to turn on otherwise.
1929 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001930 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08001931 // Run the app in safe mode if its manifest requests so or the
1932 // system is booted in safe mode.
1933 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
1934 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08001935 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1936 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001937 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1938 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1939 }
Elliott Hughesae07ecf2011-07-06 17:33:27 -07001940 if ("1".equals(SystemProperties.get("debug.jni.logging"))) {
1941 debugFlags |= Zygote.DEBUG_ENABLE_JNI_LOGGING;
1942 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001943 if ("1".equals(SystemProperties.get("debug.assert"))) {
1944 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1945 }
Jeff Brown3f9dd282011-07-08 20:02:19 -07001946
1947 // Start the process. It will either succeed and return a result containing
1948 // the PID of the new process, or else throw a RuntimeException.
1949 Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
Elliott Hughese1dfcb72011-07-08 11:08:07 -07001950 app.processName, uid, uid, gids, debugFlags,
1951 app.info.targetSdkVersion, null);
Jeff Brown3f9dd282011-07-08 20:02:19 -07001952
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001953 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
1954 synchronized (bs) {
1955 if (bs.isOnBattery()) {
1956 app.batteryStats.incStartsLocked();
1957 }
1958 }
1959
Jeff Brown3f9dd282011-07-08 20:02:19 -07001960 EventLog.writeEvent(EventLogTags.AM_PROC_START, startResult.pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001961 app.processName, hostingType,
1962 hostingNameStr != null ? hostingNameStr : "");
1963
1964 if (app.persistent) {
Jeff Brown3f9dd282011-07-08 20:02:19 -07001965 Watchdog.getInstance().processStarted(app.processName, startResult.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001966 }
1967
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001968 StringBuilder buf = mStringBuilder;
1969 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001970 buf.append("Start proc ");
1971 buf.append(app.processName);
1972 buf.append(" for ");
1973 buf.append(hostingType);
1974 if (hostingNameStr != null) {
1975 buf.append(" ");
1976 buf.append(hostingNameStr);
1977 }
1978 buf.append(": pid=");
Jeff Brown3f9dd282011-07-08 20:02:19 -07001979 buf.append(startResult.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001980 buf.append(" uid=");
1981 buf.append(uid);
1982 buf.append(" gids={");
1983 if (gids != null) {
1984 for (int gi=0; gi<gids.length; gi++) {
1985 if (gi != 0) buf.append(", ");
1986 buf.append(gids[gi]);
1987
1988 }
1989 }
1990 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08001991 Slog.i(TAG, buf.toString());
Jeff Brown3f9dd282011-07-08 20:02:19 -07001992 app.pid = startResult.pid;
1993 app.usingWrapper = startResult.usingWrapper;
1994 app.removed = false;
1995 synchronized (mPidsSelfLocked) {
1996 this.mPidsSelfLocked.put(startResult.pid, app);
1997 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1998 msg.obj = app;
1999 mHandler.sendMessageDelayed(msg, startResult.usingWrapper
2000 ? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002001 }
2002 } catch (RuntimeException e) {
2003 // XXX do better error recovery.
2004 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002005 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002006 }
2007 }
2008
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002009 void updateUsageStats(ActivityRecord resumedComponent, boolean resumed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002010 if (resumed) {
2011 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
2012 } else {
2013 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
2014 }
2015 }
2016
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002017 boolean startHomeActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002018 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
2019 && mTopAction == null) {
2020 // We are running in factory test mode, but unable to find
2021 // the factory test app, so just sit around displaying the
2022 // error message and don't try to start anything.
2023 return false;
2024 }
2025 Intent intent = new Intent(
2026 mTopAction,
2027 mTopData != null ? Uri.parse(mTopData) : null);
2028 intent.setComponent(mTopComponent);
2029 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
2030 intent.addCategory(Intent.CATEGORY_HOME);
2031 }
2032 ActivityInfo aInfo =
2033 intent.resolveActivityInfo(mContext.getPackageManager(),
2034 STOCK_PM_FLAGS);
2035 if (aInfo != null) {
2036 intent.setComponent(new ComponentName(
2037 aInfo.applicationInfo.packageName, aInfo.name));
2038 // Don't do this if the home app is currently being
2039 // instrumented.
2040 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
2041 aInfo.applicationInfo.uid);
2042 if (app == null || app.instrumentationClass == null) {
2043 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002044 mMainStack.startActivityLocked(null, intent, null, null, 0, aInfo,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002045 null, null, 0, 0, 0, false, false, null);
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002046 }
2047 }
2048
2049
2050 return true;
2051 }
2052
2053 /**
2054 * Starts the "new version setup screen" if appropriate.
2055 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002056 void startSetupActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002057 // Only do this once per boot.
2058 if (mCheckedForSetup) {
2059 return;
2060 }
2061
2062 // We will show this screen if the current one is a different
2063 // version than the last one shown, and we are not running in
2064 // low-level factory test mode.
2065 final ContentResolver resolver = mContext.getContentResolver();
2066 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
2067 Settings.Secure.getInt(resolver,
2068 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
2069 mCheckedForSetup = true;
2070
2071 // See if we should be showing the platform update setup UI.
2072 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
2073 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
2074 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
2075
2076 // We don't allow third party apps to replace this.
2077 ResolveInfo ri = null;
2078 for (int i=0; ris != null && i<ris.size(); i++) {
2079 if ((ris.get(i).activityInfo.applicationInfo.flags
2080 & ApplicationInfo.FLAG_SYSTEM) != 0) {
2081 ri = ris.get(i);
2082 break;
2083 }
2084 }
2085
2086 if (ri != null) {
2087 String vers = ri.activityInfo.metaData != null
2088 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
2089 : null;
2090 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
2091 vers = ri.activityInfo.applicationInfo.metaData.getString(
2092 Intent.METADATA_SETUP_VERSION);
2093 }
2094 String lastVers = Settings.Secure.getString(
2095 resolver, Settings.Secure.LAST_SETUP_SHOWN);
2096 if (vers != null && !vers.equals(lastVers)) {
2097 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2098 intent.setComponent(new ComponentName(
2099 ri.activityInfo.packageName, ri.activityInfo.name));
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002100 mMainStack.startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002101 null, null, 0, 0, 0, false, false, null);
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002102 }
2103 }
2104 }
2105 }
2106
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002107 CompatibilityInfo compatibilityInfoForPackageLocked(ApplicationInfo ai) {
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002108 return mCompatModePackages.compatibilityInfoForPackageLocked(ai);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002109 }
2110
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002111 public int getFrontActivityScreenCompatMode() {
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002112 synchronized (this) {
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002113 return mCompatModePackages.getFrontActivityScreenCompatModeLocked();
2114 }
2115 }
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002116
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002117 public void setFrontActivityScreenCompatMode(int mode) {
2118 synchronized (this) {
2119 mCompatModePackages.setFrontActivityScreenCompatModeLocked(mode);
2120 }
2121 }
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002122
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002123 public int getPackageScreenCompatMode(String packageName) {
2124 synchronized (this) {
2125 return mCompatModePackages.getPackageScreenCompatModeLocked(packageName);
2126 }
2127 }
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002128
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002129 public void setPackageScreenCompatMode(String packageName, int mode) {
2130 synchronized (this) {
2131 mCompatModePackages.setPackageScreenCompatModeLocked(packageName, mode);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002132 }
2133 }
2134
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07002135 public boolean getPackageAskScreenCompat(String packageName) {
2136 synchronized (this) {
2137 return mCompatModePackages.getPackageAskCompatModeLocked(packageName);
2138 }
2139 }
2140
2141 public void setPackageAskScreenCompat(String packageName, boolean ask) {
2142 synchronized (this) {
2143 mCompatModePackages.setPackageAskCompatModeLocked(packageName, ask);
2144 }
2145 }
2146
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002147 void reportResumedActivityLocked(ActivityRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002148 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002149
2150 final int identHash = System.identityHashCode(r);
2151 updateUsageStats(r, true);
2152
2153 int i = mWatchers.beginBroadcast();
2154 while (i > 0) {
2155 i--;
2156 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2157 if (w != null) {
2158 try {
2159 w.activityResuming(identHash);
2160 } catch (RemoteException e) {
2161 }
2162 }
2163 }
2164 mWatchers.finishBroadcast();
2165 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002166
Jeff Sharkeya4620792011-05-20 15:29:23 -07002167 private void dispatchForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities) {
2168 int i = mProcessObservers.beginBroadcast();
2169 while (i > 0) {
2170 i--;
2171 final IProcessObserver observer = mProcessObservers.getBroadcastItem(i);
2172 if (observer != null) {
2173 try {
2174 observer.onForegroundActivitiesChanged(pid, uid, foregroundActivities);
2175 } catch (RemoteException e) {
2176 }
2177 }
2178 }
2179 mProcessObservers.finishBroadcast();
2180 }
2181
2182 private void dispatchProcessDied(int pid, int uid) {
2183 int i = mProcessObservers.beginBroadcast();
2184 while (i > 0) {
2185 i--;
2186 final IProcessObserver observer = mProcessObservers.getBroadcastItem(i);
2187 if (observer != null) {
2188 try {
2189 observer.onProcessDied(pid, uid);
2190 } catch (RemoteException e) {
2191 }
2192 }
2193 }
2194 mProcessObservers.finishBroadcast();
2195 }
2196
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002197 final void doPendingActivityLaunchesLocked(boolean doResume) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002198 final int N = mPendingActivityLaunches.size();
2199 if (N <= 0) {
2200 return;
2201 }
2202 for (int i=0; i<N; i++) {
2203 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002204 mMainStack.startActivityUncheckedLocked(pal.r, pal.sourceRecord,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002205 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
2206 doResume && i == (N-1));
2207 }
2208 mPendingActivityLaunches.clear();
2209 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002210
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002211 public final int startActivity(IApplicationThread caller,
2212 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2213 int grantedMode, IBinder resultTo,
2214 String resultWho, int requestCode, boolean onlyIfNeeded,
2215 boolean debug) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002216 return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002217 grantedUriPermissions, grantedMode, resultTo, resultWho,
2218 requestCode, onlyIfNeeded, debug, null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002219 }
2220
2221 public final WaitResult startActivityAndWait(IApplicationThread caller,
2222 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2223 int grantedMode, IBinder resultTo,
2224 String resultWho, int requestCode, boolean onlyIfNeeded,
2225 boolean debug) {
2226 WaitResult res = new WaitResult();
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002227 mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002228 grantedUriPermissions, grantedMode, resultTo, resultWho,
2229 requestCode, onlyIfNeeded, debug, res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002230 return res;
2231 }
2232
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002233 public final int startActivityWithConfig(IApplicationThread caller,
2234 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2235 int grantedMode, IBinder resultTo,
2236 String resultWho, int requestCode, boolean onlyIfNeeded,
2237 boolean debug, Configuration config) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002238 return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002239 grantedUriPermissions, grantedMode, resultTo, resultWho,
2240 requestCode, onlyIfNeeded, debug, null, config);
2241 }
2242
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002243 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002244 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002245 IBinder resultTo, String resultWho, int requestCode,
2246 int flagsMask, int flagsValues) {
2247 // Refuse possible leaked file descriptors
2248 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
2249 throw new IllegalArgumentException("File descriptors passed in Intent");
2250 }
2251
2252 IIntentSender sender = intent.getTarget();
2253 if (!(sender instanceof PendingIntentRecord)) {
2254 throw new IllegalArgumentException("Bad PendingIntent object");
2255 }
2256
2257 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002258
2259 synchronized (this) {
2260 // If this is coming from the currently resumed activity, it is
2261 // effectively saying that app switches are allowed at this point.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002262 if (mMainStack.mResumedActivity != null
2263 && mMainStack.mResumedActivity.info.applicationInfo.uid ==
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002264 Binder.getCallingUid()) {
2265 mAppSwitchesAllowedTime = 0;
2266 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002267 }
2268
Dianne Hackborn6c418d52011-06-29 14:05:33 -07002269 return pir.sendInner(0, fillInIntent, resolvedType, null,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002270 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
2271 }
2272
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002273 public boolean startNextMatchingActivity(IBinder callingActivity,
2274 Intent intent) {
2275 // Refuse possible leaked file descriptors
2276 if (intent != null && intent.hasFileDescriptors() == true) {
2277 throw new IllegalArgumentException("File descriptors passed in Intent");
2278 }
2279
2280 synchronized (this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07002281 ActivityRecord r = mMainStack.isInStackLocked(callingActivity);
2282 if (r == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002283 return false;
2284 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002285 if (r.app == null || r.app.thread == null) {
2286 // The caller is not running... d'oh!
2287 return false;
2288 }
2289 intent = new Intent(intent);
2290 // The caller is not allowed to change the data.
2291 intent.setDataAndType(r.intent.getData(), r.intent.getType());
2292 // And we are resetting to find the next component...
2293 intent.setComponent(null);
2294
2295 ActivityInfo aInfo = null;
2296 try {
2297 List<ResolveInfo> resolves =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002298 AppGlobals.getPackageManager().queryIntentActivities(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002299 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002300 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002301
2302 // Look for the original activity in the list...
2303 final int N = resolves != null ? resolves.size() : 0;
2304 for (int i=0; i<N; i++) {
2305 ResolveInfo rInfo = resolves.get(i);
2306 if (rInfo.activityInfo.packageName.equals(r.packageName)
2307 && rInfo.activityInfo.name.equals(r.info.name)) {
2308 // We found the current one... the next matching is
2309 // after it.
2310 i++;
2311 if (i<N) {
2312 aInfo = resolves.get(i).activityInfo;
2313 }
2314 break;
2315 }
2316 }
2317 } catch (RemoteException e) {
2318 }
2319
2320 if (aInfo == null) {
2321 // Nobody who is next!
2322 return false;
2323 }
2324
2325 intent.setComponent(new ComponentName(
2326 aInfo.applicationInfo.packageName, aInfo.name));
2327 intent.setFlags(intent.getFlags()&~(
2328 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
2329 Intent.FLAG_ACTIVITY_CLEAR_TOP|
2330 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
2331 Intent.FLAG_ACTIVITY_NEW_TASK));
2332
2333 // Okay now we need to start the new activity, replacing the
2334 // currently running activity. This is a little tricky because
2335 // we want to start the new one as if the current one is finished,
2336 // but not finish the current one first so that there is no flicker.
2337 // And thus...
2338 final boolean wasFinishing = r.finishing;
2339 r.finishing = true;
2340
2341 // Propagate reply information over to the new activity.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002342 final ActivityRecord resultTo = r.resultTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002343 final String resultWho = r.resultWho;
2344 final int requestCode = r.requestCode;
2345 r.resultTo = null;
2346 if (resultTo != null) {
2347 resultTo.removeResultsLocked(r, resultWho, requestCode);
2348 }
2349
2350 final long origId = Binder.clearCallingIdentity();
2351 // XXX we are not dealing with propagating grantedUriPermissions...
2352 // those are not yet exposed to user code, so there is no need.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002353 int res = mMainStack.startActivityLocked(r.app.thread, intent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002354 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002355 requestCode, -1, r.launchedFromUid, false, false, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002356 Binder.restoreCallingIdentity(origId);
2357
2358 r.finishing = wasFinishing;
2359 if (res != START_SUCCESS) {
2360 return false;
2361 }
2362 return true;
2363 }
2364 }
2365
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002366 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002367 Intent intent, String resolvedType, IBinder resultTo,
2368 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002369
2370 // This is so super not safe, that only the system (or okay root)
2371 // can do it.
2372 final int callingUid = Binder.getCallingUid();
2373 if (callingUid != 0 && callingUid != Process.myUid()) {
2374 throw new SecurityException(
2375 "startActivityInPackage only available to the system");
2376 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002377
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002378 return mMainStack.startActivityMayWait(null, uid, intent, resolvedType,
2379 null, 0, resultTo, resultWho, requestCode, onlyIfNeeded, false, null, null);
2380 }
2381
2382 public final int startActivities(IApplicationThread caller,
2383 Intent[] intents, String[] resolvedTypes, IBinder resultTo) {
2384 return mMainStack.startActivities(caller, -1, intents, resolvedTypes, resultTo);
2385 }
2386
2387 public final int startActivitiesInPackage(int uid,
2388 Intent[] intents, String[] resolvedTypes, IBinder resultTo) {
2389
2390 // This is so super not safe, that only the system (or okay root)
2391 // can do it.
2392 final int callingUid = Binder.getCallingUid();
2393 if (callingUid != 0 && callingUid != Process.myUid()) {
2394 throw new SecurityException(
2395 "startActivityInPackage only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002396 }
2397
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002398 return mMainStack.startActivities(null, uid, intents, resolvedTypes, resultTo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002399 }
2400
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002401 final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002402 int N = mRecentTasks.size();
Dianne Hackborn7c0e75e2010-12-21 19:15:40 -08002403 // Quick case: check if the top-most recent task is the same.
2404 if (N > 0 && mRecentTasks.get(0) == task) {
2405 return;
2406 }
2407 // Remove any existing entries that are the same kind of task.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002408 for (int i=0; i<N; i++) {
2409 TaskRecord tr = mRecentTasks.get(i);
2410 if ((task.affinity != null && task.affinity.equals(tr.affinity))
2411 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
2412 mRecentTasks.remove(i);
2413 i--;
2414 N--;
2415 if (task.intent == null) {
2416 // If the new recent task we are adding is not fully
2417 // specified, then replace it with the existing recent task.
2418 task = tr;
2419 }
2420 }
2421 }
2422 if (N >= MAX_RECENT_TASKS) {
2423 mRecentTasks.remove(N-1);
2424 }
2425 mRecentTasks.add(0, task);
2426 }
2427
2428 public void setRequestedOrientation(IBinder token,
2429 int requestedOrientation) {
2430 synchronized (this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07002431 ActivityRecord r = mMainStack.isInStackLocked(token);
2432 if (r == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002433 return;
2434 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002435 final long origId = Binder.clearCallingIdentity();
2436 mWindowManager.setAppOrientation(r, requestedOrientation);
2437 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07002438 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002439 r.mayFreezeScreenLocked(r.app) ? r : null);
2440 if (config != null) {
2441 r.frozenBeforeDestroy = true;
Dianne Hackborn31ca8542011-07-19 14:58:28 -07002442 if (!updateConfigurationLocked(config, r, false)) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002443 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002444 }
2445 }
2446 Binder.restoreCallingIdentity(origId);
2447 }
2448 }
2449
2450 public int getRequestedOrientation(IBinder token) {
2451 synchronized (this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07002452 ActivityRecord r = mMainStack.isInStackLocked(token);
2453 if (r == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002454 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
2455 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002456 return mWindowManager.getAppOrientation(r);
2457 }
2458 }
2459
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002460 /**
2461 * This is the internal entry point for handling Activity.finish().
2462 *
2463 * @param token The Binder token referencing the Activity we want to finish.
2464 * @param resultCode Result code, if any, from this Activity.
2465 * @param resultData Result data (Intent), if any, from this Activity.
2466 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11002467 * @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 -08002468 */
2469 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
2470 // Refuse possible leaked file descriptors
2471 if (resultData != null && resultData.hasFileDescriptors() == true) {
2472 throw new IllegalArgumentException("File descriptors passed in Intent");
2473 }
2474
2475 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002476 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002477 // Find the first activity that is not finishing.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002478 ActivityRecord next = mMainStack.topRunningActivityLocked(token, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002479 if (next != null) {
2480 // ask watcher if this is allowed
2481 boolean resumeOK = true;
2482 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002483 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002484 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002485 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002486 }
2487
2488 if (!resumeOK) {
2489 return false;
2490 }
2491 }
2492 }
2493 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002494 boolean res = mMainStack.requestFinishActivityLocked(token, resultCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002495 resultData, "app-request");
2496 Binder.restoreCallingIdentity(origId);
2497 return res;
2498 }
2499 }
2500
Dianne Hackborn860755f2010-06-03 18:47:52 -07002501 public final void finishHeavyWeightApp() {
2502 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2503 != PackageManager.PERMISSION_GRANTED) {
2504 String msg = "Permission Denial: finishHeavyWeightApp() from pid="
2505 + Binder.getCallingPid()
2506 + ", uid=" + Binder.getCallingUid()
2507 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2508 Slog.w(TAG, msg);
2509 throw new SecurityException(msg);
2510 }
2511
2512 synchronized(this) {
2513 if (mHeavyWeightProcess == null) {
2514 return;
2515 }
2516
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002517 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>(
Dianne Hackborn860755f2010-06-03 18:47:52 -07002518 mHeavyWeightProcess.activities);
2519 for (int i=0; i<activities.size(); i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002520 ActivityRecord r = activities.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002521 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002522 int index = mMainStack.indexOfTokenLocked(r);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002523 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002524 mMainStack.finishActivityLocked(r, index, Activity.RESULT_CANCELED,
Dianne Hackborn860755f2010-06-03 18:47:52 -07002525 null, "finish-heavy");
2526 }
2527 }
2528 }
2529
2530 mHeavyWeightProcess = null;
2531 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
2532 }
2533 }
2534
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002535 public void crashApplication(int uid, int initialPid, String packageName,
2536 String message) {
2537 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2538 != PackageManager.PERMISSION_GRANTED) {
2539 String msg = "Permission Denial: crashApplication() from pid="
2540 + Binder.getCallingPid()
2541 + ", uid=" + Binder.getCallingUid()
2542 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2543 Slog.w(TAG, msg);
2544 throw new SecurityException(msg);
2545 }
2546
2547 synchronized(this) {
2548 ProcessRecord proc = null;
2549
2550 // Figure out which process to kill. We don't trust that initialPid
2551 // still has any relation to current pids, so must scan through the
2552 // list.
2553 synchronized (mPidsSelfLocked) {
2554 for (int i=0; i<mPidsSelfLocked.size(); i++) {
2555 ProcessRecord p = mPidsSelfLocked.valueAt(i);
2556 if (p.info.uid != uid) {
2557 continue;
2558 }
2559 if (p.pid == initialPid) {
2560 proc = p;
2561 break;
2562 }
2563 for (String str : p.pkgList) {
2564 if (str.equals(packageName)) {
2565 proc = p;
2566 }
2567 }
2568 }
2569 }
2570
2571 if (proc == null) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07002572 Slog.w(TAG, "crashApplication: nothing for uid=" + uid
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002573 + " initialPid=" + initialPid
2574 + " packageName=" + packageName);
2575 return;
2576 }
2577
2578 if (proc.thread != null) {
Dianne Hackborn9f531192010-08-04 17:48:03 -07002579 if (proc.pid == Process.myPid()) {
2580 Log.w(TAG, "crashApplication: trying to crash self!");
2581 return;
2582 }
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002583 long ident = Binder.clearCallingIdentity();
2584 try {
2585 proc.thread.scheduleCrash(message);
2586 } catch (RemoteException e) {
2587 }
2588 Binder.restoreCallingIdentity(ident);
2589 }
2590 }
2591 }
2592
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002593 public final void finishSubActivity(IBinder token, String resultWho,
2594 int requestCode) {
2595 synchronized(this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07002596 ActivityRecord self = mMainStack.isInStackLocked(token);
2597 if (self == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002598 return;
2599 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002600
2601 final long origId = Binder.clearCallingIdentity();
2602
2603 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002604 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2605 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002606 if (r.resultTo == self && r.requestCode == requestCode) {
2607 if ((r.resultWho == null && resultWho == null) ||
2608 (r.resultWho != null && r.resultWho.equals(resultWho))) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002609 mMainStack.finishActivityLocked(r, i,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002610 Activity.RESULT_CANCELED, null, "request-sub");
2611 }
2612 }
2613 }
2614
2615 Binder.restoreCallingIdentity(origId);
2616 }
2617 }
2618
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002619 public boolean willActivityBeVisible(IBinder token) {
2620 synchronized(this) {
2621 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002622 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2623 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002624 if (r == token) {
2625 return true;
2626 }
2627 if (r.fullscreen && !r.finishing) {
2628 return false;
2629 }
2630 }
2631 return true;
2632 }
2633 }
2634
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002635 public void overridePendingTransition(IBinder token, String packageName,
2636 int enterAnim, int exitAnim) {
2637 synchronized(this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07002638 ActivityRecord self = mMainStack.isInStackLocked(token);
2639 if (self == null) {
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002640 return;
2641 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002642
2643 final long origId = Binder.clearCallingIdentity();
2644
2645 if (self.state == ActivityState.RESUMED
2646 || self.state == ActivityState.PAUSING) {
2647 mWindowManager.overridePendingAppTransition(packageName,
2648 enterAnim, exitAnim);
2649 }
2650
2651 Binder.restoreCallingIdentity(origId);
2652 }
2653 }
2654
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002655 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002656 * Main function for removing an existing process from the activity manager
2657 * as a result of that process going away. Clears out all connections
2658 * to the process.
2659 */
2660 private final void handleAppDiedLocked(ProcessRecord app,
2661 boolean restarting) {
2662 cleanUpApplicationRecordLocked(app, restarting, -1);
2663 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002664 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002665 }
2666
2667 // Just in case...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002668 if (mMainStack.mPausingActivity != null && mMainStack.mPausingActivity.app == app) {
2669 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " +mMainStack.mPausingActivity);
2670 mMainStack.mPausingActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002671 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002672 if (mMainStack.mLastPausedActivity != null && mMainStack.mLastPausedActivity.app == app) {
2673 mMainStack.mLastPausedActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002674 }
2675
2676 // Remove this application's activities from active lists.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002677 mMainStack.removeHistoryRecordsForAppLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002678
2679 boolean atTop = true;
2680 boolean hasVisibleActivities = false;
2681
2682 // Clean out the history list.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002683 int i = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002684 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002685 TAG, "Removing app " + app + " from history with " + i + " entries");
2686 while (i > 0) {
2687 i--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002688 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002689 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002690 TAG, "Record #" + i + " " + r + ": app=" + r.app);
2691 if (r.app == app) {
2692 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002693 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002694 TAG, "Removing this entry! frozen=" + r.haveState
2695 + " finishing=" + r.finishing);
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -08002696 r.makeFinishing();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002697 mMainStack.mHistory.remove(i);
Dianne Hackbornf26fd992011-04-08 18:14:09 -07002698 r.takeFromHistory();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002699 mWindowManager.removeAppToken(r);
2700 if (VALIDATE_TOKENS) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002701 mWindowManager.validateAppTokens(mMainStack.mHistory);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002702 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002703 r.removeUriPermissionsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002704
2705 } else {
2706 // We have the current state for this activity, so
2707 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002708 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002709 TAG, "Keeping entry, setting app to null");
2710 if (r.visible) {
2711 hasVisibleActivities = true;
2712 }
2713 r.app = null;
2714 r.nowVisible = false;
2715 if (!r.haveState) {
2716 r.icicle = null;
2717 }
2718 }
2719
Dianne Hackbornce86ba82011-07-13 19:33:41 -07002720 r.stack.cleanUpActivityLocked(r, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002721 }
2722 atTop = false;
2723 }
2724
2725 app.activities.clear();
2726
2727 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002728 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002729 + " running instrumentation " + app.instrumentationClass);
2730 Bundle info = new Bundle();
2731 info.putString("shortMsg", "Process crashed.");
2732 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
2733 }
2734
2735 if (!restarting) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002736 if (!mMainStack.resumeTopActivityLocked(null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002737 // If there was nothing to resume, and we are not already
2738 // restarting this process, but there is a visible activity that
2739 // is hosted by the process... then make sure all visible
2740 // activities are running, taking care of restarting this
2741 // process.
2742 if (hasVisibleActivities) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002743 mMainStack.ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002744 }
2745 }
2746 }
2747 }
2748
2749 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
2750 IBinder threadBinder = thread.asBinder();
2751
2752 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002753 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2754 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002755 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
2756 return i;
2757 }
2758 }
2759 return -1;
2760 }
2761
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002762 final ProcessRecord getRecordForAppLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002763 IApplicationThread thread) {
2764 if (thread == null) {
2765 return null;
2766 }
2767
2768 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002769 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002770 }
2771
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002772 final void appDiedLocked(ProcessRecord app, int pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002773 IApplicationThread thread) {
2774
2775 mProcDeaths[0]++;
2776
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07002777 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
2778 synchronized (stats) {
2779 stats.noteProcessDiedLocked(app.info.uid, pid);
2780 }
2781
Magnus Edlund7bb25812010-02-24 15:45:06 +01002782 // Clean up already done if the process has been re-started.
2783 if (app.pid == pid && app.thread != null &&
2784 app.thread.asBinder() == thread.asBinder()) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07002785 if (!app.killedBackground) {
2786 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
2787 + ") has died.");
2788 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08002789 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002790 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002791 TAG, "Dying app: " + app + ", pid: " + pid
2792 + ", thread: " + thread.asBinder());
2793 boolean doLowMem = app.instrumentationClass == null;
2794 handleAppDiedLocked(app, false);
2795
2796 if (doLowMem) {
2797 // If there are no longer any background processes running,
2798 // and the app that died was not running instrumentation,
2799 // then tell everyone we are now low on memory.
2800 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002801 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2802 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002803 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
2804 haveBg = true;
2805 break;
2806 }
2807 }
2808
2809 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002810 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002811 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002812 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002813 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2814 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07002815 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002816 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
2817 // The low memory report is overriding any current
2818 // state for a GC request. Make sure to do
Dianne Hackborn32907cf2010-06-10 17:50:20 -07002819 // heavy/important/visible/foreground processes first.
2820 if (rec.setAdj <= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002821 rec.lastRequestedGc = 0;
2822 } else {
2823 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002824 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002825 rec.reportLowMemory = true;
2826 rec.lastLowMemory = now;
2827 mProcessesToGc.remove(rec);
2828 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002829 }
2830 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002831 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002832 }
2833 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01002834 } else if (app.pid != pid) {
2835 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002836 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01002837 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08002838 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002839 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002840 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002841 + thread.asBinder());
2842 }
2843 }
2844
Dan Egnor42471dd2010-01-07 17:25:22 -08002845 /**
2846 * If a stack trace dump file is configured, dump process stack traces.
Christopher Tate6ee412d2010-05-28 12:01:56 -07002847 * @param clearTraces causes the dump file to be erased prior to the new
2848 * traces being written, if true; when false, the new traces will be
2849 * appended to any existing file content.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002850 * @param firstPids of dalvik VM processes to dump stack traces for first
2851 * @param lastPids of dalvik VM processes to dump stack traces for last
Dan Egnor42471dd2010-01-07 17:25:22 -08002852 * @return file containing stack traces, or null if no dump file is configured
2853 */
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002854 public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> firstPids,
2855 ProcessStats processStats, SparseArray<Boolean> lastPids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002856 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
2857 if (tracesPath == null || tracesPath.length() == 0) {
2858 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002859 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002860
2861 File tracesFile = new File(tracesPath);
2862 try {
2863 File tracesDir = tracesFile.getParentFile();
2864 if (!tracesDir.exists()) tracesFile.mkdirs();
2865 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
2866
Christopher Tate6ee412d2010-05-28 12:01:56 -07002867 if (clearTraces && tracesFile.exists()) tracesFile.delete();
Dan Egnor42471dd2010-01-07 17:25:22 -08002868 tracesFile.createNewFile();
2869 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
2870 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002871 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08002872 return null;
2873 }
2874
2875 // Use a FileObserver to detect when traces finish writing.
2876 // The order of traces is considered important to maintain for legibility.
2877 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
2878 public synchronized void onEvent(int event, String path) { notify(); }
2879 };
2880
2881 try {
2882 observer.startWatching();
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002883
2884 // First collect all of the stacks of the most important pids.
2885 try {
2886 int num = firstPids.size();
2887 for (int i = 0; i < num; i++) {
2888 synchronized (observer) {
2889 Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT);
2890 observer.wait(200); // Wait for write-close, give up after 200msec
2891 }
2892 }
2893 } catch (InterruptedException e) {
2894 Log.wtf(TAG, e);
2895 }
2896
2897 // Next measure CPU usage.
2898 if (processStats != null) {
2899 processStats.init();
2900 System.gc();
2901 processStats.update();
2902 try {
2903 synchronized (processStats) {
2904 processStats.wait(500); // measure over 1/2 second.
2905 }
2906 } catch (InterruptedException e) {
2907 }
2908 processStats.update();
2909
2910 // We'll take the stack crawls of just the top apps using CPU.
2911 final int N = processStats.countWorkingStats();
2912 int numProcs = 0;
2913 for (int i=0; i<N && numProcs<5; i++) {
2914 ProcessStats.Stats stats = processStats.getWorkingStats(i);
2915 if (lastPids.indexOfKey(stats.pid) >= 0) {
2916 numProcs++;
2917 try {
2918 synchronized (observer) {
2919 Process.sendSignal(stats.pid, Process.SIGNAL_QUIT);
2920 observer.wait(200); // Wait for write-close, give up after 200msec
2921 }
2922 } catch (InterruptedException e) {
2923 Log.wtf(TAG, e);
2924 }
2925
2926 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002927 }
2928 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002929
2930 return tracesFile;
2931
Dan Egnor42471dd2010-01-07 17:25:22 -08002932 } finally {
2933 observer.stopWatching();
2934 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002935 }
2936
Jeff Brown4d94a762010-09-23 11:33:28 -07002937 private final class AppNotResponding implements Runnable {
2938 private final ProcessRecord mApp;
2939 private final String mAnnotation;
2940
2941 public AppNotResponding(ProcessRecord app, String annotation) {
2942 mApp = app;
2943 mAnnotation = annotation;
2944 }
2945
2946 @Override
2947 public void run() {
2948 appNotResponding(mApp, null, null, mAnnotation);
2949 }
2950 }
2951
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002952 final void appNotResponding(ProcessRecord app, ActivityRecord activity,
2953 ActivityRecord parent, final String annotation) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002954 ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
2955 SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20);
2956
Dianne Hackborn287952c2010-09-22 22:34:31 -07002957 if (mController != null) {
2958 try {
2959 // 0 == continue, -1 = kill process immediately
2960 int res = mController.appEarlyNotResponding(app.processName, app.pid, annotation);
2961 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2962 } catch (RemoteException e) {
2963 mController = null;
2964 }
2965 }
2966
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002967 long anrTime = SystemClock.uptimeMillis();
2968 if (MONITOR_CPU_USAGE) {
2969 updateCpuStatsNow();
2970 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002971
2972 synchronized (this) {
2973 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
2974 if (mShuttingDown) {
2975 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
2976 return;
2977 } else if (app.notResponding) {
2978 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
2979 return;
2980 } else if (app.crashing) {
2981 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
2982 return;
2983 }
2984
2985 // In case we come through here for the same app before completing
2986 // this one, mark as anring now so we will bail out.
2987 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08002988
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002989 // Log the ANR to the event log.
2990 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
2991 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08002992
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002993 // Dump thread traces as quickly as we can, starting with "interesting" processes.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002994 firstPids.add(app.pid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002995
2996 int parentPid = app.pid;
2997 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002998 if (parentPid != app.pid) firstPids.add(parentPid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002999
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003000 if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08003001
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003002 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
3003 ProcessRecord r = mLruProcesses.get(i);
3004 if (r != null && r.thread != null) {
3005 int pid = r.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003006 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
3007 if (r.persistent) {
3008 firstPids.add(pid);
3009 } else {
3010 lastPids.put(pid, Boolean.TRUE);
3011 }
3012 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003013 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003014 }
3015 }
3016
Dan Egnor42471dd2010-01-07 17:25:22 -08003017 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07003018 StringBuilder info = mStringBuilder;
3019 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08003020 info.append("ANR in ").append(app.processName);
3021 if (activity != null && activity.shortComponentName != null) {
3022 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07003023 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08003024 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003025 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08003026 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003027 }
Dan Egnor42471dd2010-01-07 17:25:22 -08003028 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08003029 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003030 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003031
Dianne Hackborn287952c2010-09-22 22:34:31 -07003032 final ProcessStats processStats = new ProcessStats(true);
3033
3034 File tracesFile = dumpStackTraces(true, firstPids, processStats, lastPids);
3035
Dan Egnor42471dd2010-01-07 17:25:22 -08003036 String cpuInfo = null;
3037 if (MONITOR_CPU_USAGE) {
3038 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003039 synchronized (mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003040 cpuInfo = mProcessStats.printCurrentState(anrTime);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003041 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003042 info.append(processStats.printCurrentLoad());
Dan Egnor42471dd2010-01-07 17:25:22 -08003043 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003044 }
3045
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003046 info.append(processStats.printCurrentState(anrTime));
3047
Joe Onorato8a9b2202010-02-26 18:56:32 -08003048 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08003049 if (tracesFile == null) {
3050 // There is no trace file, so dump (only) the alleged culprit's threads to the log
3051 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
3052 }
3053
3054 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
3055
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003056 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003057 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08003058 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
3059 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003060 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08003061 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
3062 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003063 }
3064 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003065 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003066 }
3067 }
3068
Dan Egnor42471dd2010-01-07 17:25:22 -08003069 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
3070 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
3071 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003072
3073 synchronized (this) {
3074 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07003075 Slog.w(TAG, "Killing " + app + ": background ANR");
3076 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
3077 app.processName, app.setAdj, "background ANR");
3078 Process.killProcessQuiet(app.pid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003079 return;
3080 }
3081
3082 // Set the app's notResponding state, and look up the errorReportReceiver
3083 makeAppNotRespondingLocked(app,
3084 activity != null ? activity.shortComponentName : null,
3085 annotation != null ? "ANR " + annotation : "ANR",
3086 info.toString());
3087
3088 // Bring up the infamous App Not Responding dialog
3089 Message msg = Message.obtain();
3090 HashMap map = new HashMap();
3091 msg.what = SHOW_NOT_RESPONDING_MSG;
3092 msg.obj = map;
3093 map.put("app", app);
3094 if (activity != null) {
3095 map.put("activity", activity);
3096 }
3097
3098 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08003099 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003100 }
3101
Dianne Hackborn0dad3642010-09-09 21:25:35 -07003102 final void showLaunchWarningLocked(final ActivityRecord cur, final ActivityRecord next) {
3103 if (!mLaunchWarningShown) {
3104 mLaunchWarningShown = true;
3105 mHandler.post(new Runnable() {
3106 @Override
3107 public void run() {
3108 synchronized (ActivityManagerService.this) {
3109 final Dialog d = new LaunchWarningWindow(mContext, cur, next);
3110 d.show();
3111 mHandler.postDelayed(new Runnable() {
3112 @Override
3113 public void run() {
3114 synchronized (ActivityManagerService.this) {
3115 d.dismiss();
3116 mLaunchWarningShown = false;
3117 }
3118 }
3119 }, 4000);
3120 }
3121 }
3122 });
3123 }
3124 }
3125
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003126 public boolean clearApplicationUserData(final String packageName,
3127 final IPackageDataObserver observer) {
3128 int uid = Binder.getCallingUid();
3129 int pid = Binder.getCallingPid();
3130 long callingId = Binder.clearCallingIdentity();
3131 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003132 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003133 int pkgUid = -1;
3134 synchronized(this) {
3135 try {
3136 pkgUid = pm.getPackageUid(packageName);
3137 } catch (RemoteException e) {
3138 }
3139 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003140 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003141 return false;
3142 }
3143 if (uid == pkgUid || checkComponentPermission(
3144 android.Manifest.permission.CLEAR_APP_USER_DATA,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08003145 pid, uid, -1, true)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003146 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003147 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003148 } else {
3149 throw new SecurityException(pid+" does not have permission:"+
3150 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
3151 "for process:"+packageName);
3152 }
3153 }
3154
3155 try {
3156 //clear application user data
3157 pm.clearApplicationUserData(packageName, observer);
3158 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
3159 Uri.fromParts("package", packageName, null));
3160 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003161 broadcastIntentInPackage("android", Process.SYSTEM_UID, intent,
3162 null, null, 0, null, null, null, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003163 } catch (RemoteException e) {
3164 }
3165 } finally {
3166 Binder.restoreCallingIdentity(callingId);
3167 }
3168 return true;
3169 }
3170
Dianne Hackborn03abb812010-01-04 18:43:19 -08003171 public void killBackgroundProcesses(final String packageName) {
3172 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
3173 != PackageManager.PERMISSION_GRANTED &&
3174 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
3175 != PackageManager.PERMISSION_GRANTED) {
3176 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003177 + Binder.getCallingPid()
3178 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08003179 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003180 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003181 throw new SecurityException(msg);
3182 }
3183
3184 long callingId = Binder.clearCallingIdentity();
3185 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003186 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003187 int pkgUid = -1;
3188 synchronized(this) {
3189 try {
3190 pkgUid = pm.getPackageUid(packageName);
3191 } catch (RemoteException e) {
3192 }
3193 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003194 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003195 return;
3196 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003197 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003198 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003199 }
3200 } finally {
3201 Binder.restoreCallingIdentity(callingId);
3202 }
3203 }
3204
3205 public void forceStopPackage(final String packageName) {
3206 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
3207 != PackageManager.PERMISSION_GRANTED) {
3208 String msg = "Permission Denial: forceStopPackage() from pid="
3209 + Binder.getCallingPid()
3210 + ", uid=" + Binder.getCallingUid()
3211 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003212 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003213 throw new SecurityException(msg);
3214 }
3215
3216 long callingId = Binder.clearCallingIdentity();
3217 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003218 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn03abb812010-01-04 18:43:19 -08003219 int pkgUid = -1;
3220 synchronized(this) {
3221 try {
3222 pkgUid = pm.getPackageUid(packageName);
3223 } catch (RemoteException e) {
3224 }
3225 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003226 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003227 return;
3228 }
3229 forceStopPackageLocked(packageName, pkgUid);
Dianne Hackborne7f97212011-02-24 14:40:20 -08003230 try {
3231 pm.setPackageStoppedState(packageName, true);
3232 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08003233 } catch (IllegalArgumentException e) {
3234 Slog.w(TAG, "Failed trying to unstop package "
3235 + packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08003236 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003237 }
3238 } finally {
3239 Binder.restoreCallingIdentity(callingId);
3240 }
3241 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003242
3243 /*
3244 * The pkg name and uid have to be specified.
3245 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
3246 */
3247 public void killApplicationWithUid(String pkg, int uid) {
3248 if (pkg == null) {
3249 return;
3250 }
3251 // Make sure the uid is valid.
3252 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003253 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003254 return;
3255 }
3256 int callerUid = Binder.getCallingUid();
3257 // Only the system server can kill an application
3258 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07003259 // Post an aysnc message to kill the application
3260 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
3261 msg.arg1 = uid;
3262 msg.arg2 = 0;
3263 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07003264 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003265 } else {
3266 throw new SecurityException(callerUid + " cannot kill pkg: " +
3267 pkg);
3268 }
3269 }
3270
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003271 public void closeSystemDialogs(String reason) {
3272 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003273 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003274 if (reason != null) {
3275 intent.putExtra("reason", reason);
3276 }
3277
3278 final int uid = Binder.getCallingUid();
3279 final long origId = Binder.clearCallingIdentity();
3280 synchronized (this) {
3281 int i = mWatchers.beginBroadcast();
3282 while (i > 0) {
3283 i--;
3284 IActivityWatcher w = mWatchers.getBroadcastItem(i);
3285 if (w != null) {
3286 try {
3287 w.closingSystemDialogs(reason);
3288 } catch (RemoteException e) {
3289 }
3290 }
3291 }
3292 mWatchers.finishBroadcast();
3293
Dianne Hackbornffa42482009-09-23 22:20:11 -07003294 mWindowManager.closeSystemDialogs(reason);
3295
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003296 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3297 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackbornffa42482009-09-23 22:20:11 -07003298 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003299 r.stack.finishActivityLocked(r, i,
Dianne Hackbornffa42482009-09-23 22:20:11 -07003300 Activity.RESULT_CANCELED, null, "close-sys");
3301 }
3302 }
3303
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003304 broadcastIntentLocked(null, null, intent, null,
3305 null, 0, null, null, null, false, false, -1, uid);
3306 }
3307 Binder.restoreCallingIdentity(origId);
3308 }
3309
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003310 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003311 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003312 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
3313 for (int i=pids.length-1; i>=0; i--) {
3314 infos[i] = new Debug.MemoryInfo();
3315 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003316 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003317 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003318 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07003319
3320 public void killApplicationProcess(String processName, int uid) {
3321 if (processName == null) {
3322 return;
3323 }
3324
3325 int callerUid = Binder.getCallingUid();
3326 // Only the system server can kill an application
3327 if (callerUid == Process.SYSTEM_UID) {
3328 synchronized (this) {
3329 ProcessRecord app = getProcessRecordLocked(processName, uid);
Christopher Tate4a627c72011-04-01 14:43:32 -07003330 if (app != null && app.thread != null) {
Christopher Tate5e1ab332009-09-01 20:32:49 -07003331 try {
3332 app.thread.scheduleSuicide();
3333 } catch (RemoteException e) {
3334 // If the other end already died, then our work here is done.
3335 }
3336 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003337 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07003338 + processName + " / " + uid);
3339 }
3340 }
3341 } else {
3342 throw new SecurityException(callerUid + " cannot kill app process: " +
3343 processName);
3344 }
3345 }
3346
Dianne Hackborn03abb812010-01-04 18:43:19 -08003347 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003348 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003349 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
3350 Uri.fromParts("package", packageName, null));
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003351 if (!mProcessesReady) {
3352 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
3353 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003354 intent.putExtra(Intent.EXTRA_UID, uid);
3355 broadcastIntentLocked(null, null, intent,
3356 null, null, 0, null, null, null,
3357 false, false, MY_PID, Process.SYSTEM_UID);
3358 }
3359
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003360 private final boolean killPackageProcessesLocked(String packageName, int uid,
3361 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003362 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003363
Dianne Hackborn03abb812010-01-04 18:43:19 -08003364 // Remove all processes this package may have touched: all with the
3365 // same UID (except for the system or root user), and all whose name
3366 // matches the package name.
3367 final String procNamePrefix = packageName + ":";
3368 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
3369 final int NA = apps.size();
3370 for (int ia=0; ia<NA; ia++) {
3371 ProcessRecord app = apps.valueAt(ia);
Christopher Tate064d8422011-07-26 15:38:07 -07003372 if (app.persistent) {
3373 // we don't kill persistent processes
3374 continue;
3375 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003376 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003377 if (doit) {
3378 procs.add(app);
3379 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003380 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
3381 || app.processName.equals(packageName)
3382 || app.processName.startsWith(procNamePrefix)) {
3383 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003384 if (!doit) {
3385 return true;
3386 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003387 app.removed = true;
3388 procs.add(app);
3389 }
3390 }
3391 }
3392 }
3393
3394 int N = procs.size();
3395 for (int i=0; i<N; i++) {
3396 removeProcessLocked(procs.get(i), callerWillRestart);
3397 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003398 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08003399 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003400
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003401 private final boolean forceStopPackageLocked(String name, int uid,
3402 boolean callerWillRestart, boolean purgeCache, boolean doit) {
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07003403 int i;
3404 int N;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003405
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003406 if (uid < 0) {
3407 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003408 uid = AppGlobals.getPackageManager().getPackageUid(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003409 } catch (RemoteException e) {
3410 }
3411 }
3412
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003413 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003414 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003415
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003416 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
3417 while (badApps.hasNext()) {
3418 SparseArray<Long> ba = badApps.next();
3419 if (ba.get(uid) != null) {
3420 badApps.remove();
3421 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003422 }
3423 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003424
3425 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
3426 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003427
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003428 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3429 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Christopher Tate064d8422011-07-26 15:38:07 -07003430 if (r.packageName.equals(name)
3431 && (r.app == null || !r.app.persistent)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003432 if (!doit) {
3433 return true;
3434 }
3435 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003436 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003437 if (r.app != null) {
3438 r.app.removed = true;
3439 }
3440 r.app = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003441 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003442 }
3443 }
3444
3445 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
3446 for (ServiceRecord service : mServices.values()) {
Christopher Tate064d8422011-07-26 15:38:07 -07003447 if (service.packageName.equals(name)
3448 && (service.app == null || !service.app.persistent)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003449 if (!doit) {
3450 return true;
3451 }
3452 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003453 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003454 if (service.app != null) {
3455 service.app.removed = true;
3456 }
3457 service.app = null;
3458 services.add(service);
3459 }
3460 }
3461
3462 N = services.size();
3463 for (i=0; i<N; i++) {
3464 bringDownServiceLocked(services.get(i), true);
3465 }
3466
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003467 if (doit) {
3468 if (purgeCache) {
3469 AttributeCache ac = AttributeCache.instance();
3470 if (ac != null) {
3471 ac.removePackage(name);
3472 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003473 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003474 mMainStack.resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003475 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003476
3477 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003478 }
3479
3480 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
3481 final String name = app.processName;
3482 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003483 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003484 TAG, "Force removing process " + app + " (" + name
3485 + "/" + uid + ")");
3486
3487 mProcessNames.remove(name, uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003488 if (mHeavyWeightProcess == app) {
3489 mHeavyWeightProcess = null;
3490 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3491 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003492 boolean needRestart = false;
3493 if (app.pid > 0 && app.pid != MY_PID) {
3494 int pid = app.pid;
3495 synchronized (mPidsSelfLocked) {
3496 mPidsSelfLocked.remove(pid);
3497 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3498 }
3499 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003500 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003501 Process.killProcess(pid);
3502
3503 if (app.persistent) {
3504 if (!callerWillRestart) {
3505 addAppLocked(app.info);
3506 } else {
3507 needRestart = true;
3508 }
3509 }
3510 } else {
3511 mRemovedProcesses.add(app);
3512 }
3513
3514 return needRestart;
3515 }
3516
3517 private final void processStartTimedOutLocked(ProcessRecord app) {
3518 final int pid = app.pid;
3519 boolean gone = false;
3520 synchronized (mPidsSelfLocked) {
3521 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
3522 if (knownApp != null && knownApp.thread == null) {
3523 mPidsSelfLocked.remove(pid);
3524 gone = true;
3525 }
3526 }
3527
3528 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003529 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003530 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003531 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003532 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003533 if (mHeavyWeightProcess == app) {
3534 mHeavyWeightProcess = null;
3535 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3536 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003537 // Take care of any launching providers waiting for this process.
3538 checkAppInLaunchingProvidersLocked(app, true);
3539 // Take care of any services that are waiting for the process.
3540 for (int i=0; i<mPendingServices.size(); i++) {
3541 ServiceRecord sr = mPendingServices.get(i);
3542 if (app.info.uid == sr.appInfo.uid
3543 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003544 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003545 mPendingServices.remove(i);
3546 i--;
3547 bringDownServiceLocked(sr, true);
3548 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003549 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07003550 EventLog.writeEvent(EventLogTags.AM_KILL, pid,
3551 app.processName, app.setAdj, "start timeout");
3552 Process.killProcessQuiet(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07003553 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003554 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07003555 try {
3556 IBackupManager bm = IBackupManager.Stub.asInterface(
3557 ServiceManager.getService(Context.BACKUP_SERVICE));
3558 bm.agentDisconnected(app.info.packageName);
3559 } catch (RemoteException e) {
3560 // Can't happen; the backup manager is local
3561 }
3562 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003563 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003564 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003565 mPendingBroadcast.state = BroadcastRecord.IDLE;
3566 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003567 mPendingBroadcast = null;
3568 scheduleBroadcastsLocked();
3569 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003570 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003571 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003572 }
3573 }
3574
3575 private final boolean attachApplicationLocked(IApplicationThread thread,
3576 int pid) {
3577
3578 // Find the application record that is being attached... either via
3579 // the pid if we are running in multiple processes, or just pull the
3580 // next app record if we are emulating process with anonymous threads.
3581 ProcessRecord app;
3582 if (pid != MY_PID && pid >= 0) {
3583 synchronized (mPidsSelfLocked) {
3584 app = mPidsSelfLocked.get(pid);
3585 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003586 } else {
3587 app = null;
3588 }
3589
3590 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003591 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003592 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003593 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003594 if (pid > 0 && pid != MY_PID) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07003595 Process.killProcessQuiet(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003596 } else {
3597 try {
3598 thread.scheduleExit();
3599 } catch (Exception e) {
3600 // Ignore exceptions.
3601 }
3602 }
3603 return false;
3604 }
3605
3606 // If this application record is still attached to a previous
3607 // process, clean it up now.
3608 if (app.thread != null) {
3609 handleAppDiedLocked(app, true);
3610 }
3611
3612 // Tell the process all about itself.
3613
Joe Onorato8a9b2202010-02-26 18:56:32 -08003614 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003615 TAG, "Binding process pid " + pid + " to record " + app);
3616
3617 String processName = app.processName;
3618 try {
Dianne Hackborn1b64e0d2011-07-17 15:23:59 -07003619 AppDeathRecipient adr = new AppDeathRecipient(
3620 app, pid, thread);
3621 thread.asBinder().linkToDeath(adr, 0);
3622 app.deathRecipient = adr;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003623 } catch (RemoteException e) {
3624 app.resetPackageList();
3625 startProcessLocked(app, "link fail", processName);
3626 return false;
3627 }
3628
Doug Zongker2bec3d42009-12-04 12:52:44 -08003629 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003630
3631 app.thread = thread;
3632 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08003633 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
3634 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003635 app.forcingToForeground = null;
3636 app.foregroundServices = false;
Dianne Hackbornf0754f5b2011-07-21 16:02:07 -07003637 app.hasShownUi = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003638 app.debugging = false;
3639
3640 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3641
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003642 boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003643 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003644
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003645 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003646 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003647 }
3648
Joe Onorato8a9b2202010-02-26 18:56:32 -08003649 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003650 TAG, "New app record " + app
3651 + " thread=" + thread.asBinder() + " pid=" + pid);
3652 try {
3653 int testMode = IApplicationThread.DEBUG_OFF;
3654 if (mDebugApp != null && mDebugApp.equals(processName)) {
3655 testMode = mWaitForDebugger
3656 ? IApplicationThread.DEBUG_WAIT
3657 : IApplicationThread.DEBUG_ON;
3658 app.debugging = true;
3659 if (mDebugTransient) {
3660 mDebugApp = mOrigDebugApp;
3661 mWaitForDebugger = mOrigWaitForDebugger;
3662 }
3663 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003664
Christopher Tate181fafa2009-05-14 11:12:14 -07003665 // If the app is being launched for restore or full backup, set it up specially
3666 boolean isRestrictedBackupMode = false;
3667 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
3668 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
Christopher Tate75a99702011-05-18 16:28:19 -07003669 || (mBackupTarget.backupMode == BackupRecord.RESTORE_FULL)
Christopher Tate181fafa2009-05-14 11:12:14 -07003670 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
3671 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003672
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07003673 ensurePackageDexOpt(app.instrumentationInfo != null
3674 ? app.instrumentationInfo.packageName
3675 : app.info.packageName);
3676 if (app.instrumentationClass != null) {
3677 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003678 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003679 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003680 + processName + " with config " + mConfiguration);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04003681 ApplicationInfo appInfo = app.instrumentationInfo != null
3682 ? app.instrumentationInfo : app.info;
Dianne Hackborn8ea5e1d2011-05-27 16:45:31 -07003683 app.compat = compatibilityInfoForPackageLocked(appInfo);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04003684 thread.bindApplication(processName, appInfo, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003685 app.instrumentationClass, app.instrumentationProfileFile,
3686 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003687 isRestrictedBackupMode || !normalMode,
Dianne Hackborn8ea5e1d2011-05-27 16:45:31 -07003688 mConfiguration, app.compat, getCommonServicesLocked(),
Svetoslav Ganov54d068e2011-03-02 12:58:40 -08003689 mCoreSettingsObserver.getCoreSettingsLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003690 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003691 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003692 } catch (Exception e) {
3693 // todo: Yikes! What should we do? For now we will try to
3694 // start another process, but that could easily get us in
3695 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08003696 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003697
3698 app.resetPackageList();
Dianne Hackborn1b64e0d2011-07-17 15:23:59 -07003699 app.unlinkDeathRecipient();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003700 startProcessLocked(app, "bind fail", processName);
3701 return false;
3702 }
3703
3704 // Remove this record from the list of starting applications.
3705 mPersistentStartingProcesses.remove(app);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003706 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
3707 "Attach application locked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003708 mProcessesOnHold.remove(app);
3709
3710 boolean badApp = false;
3711 boolean didSomething = false;
3712
3713 // See if the top visible activity is waiting to run in this process...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003714 ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07003715 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003716 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
3717 && processName.equals(hr.processName)) {
3718 try {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003719 if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003720 didSomething = true;
3721 }
3722 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003723 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003724 + hr.intent.getComponent().flattenToShortString(), e);
3725 badApp = true;
3726 }
3727 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003728 mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003729 }
3730 }
3731
3732 // Find any services that should be running in this process...
3733 if (!badApp && mPendingServices.size() > 0) {
3734 ServiceRecord sr = null;
3735 try {
3736 for (int i=0; i<mPendingServices.size(); i++) {
3737 sr = mPendingServices.get(i);
3738 if (app.info.uid != sr.appInfo.uid
3739 || !processName.equals(sr.processName)) {
3740 continue;
3741 }
3742
3743 mPendingServices.remove(i);
3744 i--;
3745 realStartServiceLocked(sr, app);
3746 didSomething = true;
3747 }
3748 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003749 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003750 + sr.shortName, e);
3751 badApp = true;
3752 }
3753 }
3754
3755 // Check if the next broadcast receiver is in this process...
3756 BroadcastRecord br = mPendingBroadcast;
3757 if (!badApp && br != null && br.curApp == app) {
3758 try {
3759 mPendingBroadcast = null;
3760 processCurBroadcastLocked(br, app);
3761 didSomething = true;
3762 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003763 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003764 + br.curComponent.flattenToShortString(), e);
3765 badApp = true;
Jeff Brown4d94a762010-09-23 11:33:28 -07003766 logBroadcastReceiverDiscardLocked(br);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003767 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
3768 br.resultExtras, br.resultAbort, true);
3769 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01003770 // We need to reset the state if we fails to start the receiver.
3771 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003772 }
3773 }
3774
Christopher Tate181fafa2009-05-14 11:12:14 -07003775 // Check whether the next backup agent is in this process...
3776 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003777 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003778 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07003779 try {
Dianne Hackborne2515ee2011-04-27 18:52:56 -04003780 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo,
3781 compatibilityInfoForPackageLocked(mBackupTarget.appInfo),
3782 mBackupTarget.backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -07003783 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003784 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07003785 e.printStackTrace();
3786 }
3787 }
3788
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003789 if (badApp) {
3790 // todo: Also need to kill application to deal with all
3791 // kinds of exceptions.
3792 handleAppDiedLocked(app, false);
3793 return false;
3794 }
3795
3796 if (!didSomething) {
3797 updateOomAdjLocked();
3798 }
3799
3800 return true;
3801 }
3802
3803 public final void attachApplication(IApplicationThread thread) {
3804 synchronized (this) {
3805 int callingPid = Binder.getCallingPid();
3806 final long origId = Binder.clearCallingIdentity();
3807 attachApplicationLocked(thread, callingPid);
3808 Binder.restoreCallingIdentity(origId);
3809 }
3810 }
3811
Dianne Hackborne88846e2009-09-30 21:34:25 -07003812 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003813 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003814 mMainStack.activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003815 Binder.restoreCallingIdentity(origId);
3816 }
3817
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003818 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003819 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003820 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003821 mWindowManager.enableScreenAfterBoot();
3822 }
3823
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003824 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003825 IntentFilter pkgFilter = new IntentFilter();
3826 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
3827 pkgFilter.addDataScheme("package");
3828 mContext.registerReceiver(new BroadcastReceiver() {
3829 @Override
3830 public void onReceive(Context context, Intent intent) {
3831 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
3832 if (pkgs != null) {
3833 for (String pkg : pkgs) {
Vairavan Srinivasan61f07652010-07-22 13:36:40 -07003834 synchronized (ActivityManagerService.this) {
3835 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
3836 setResultCode(Activity.RESULT_OK);
3837 return;
3838 }
3839 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003840 }
3841 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003842 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003843 }, pkgFilter);
3844
3845 synchronized (this) {
3846 // Ensure that any processes we had put on hold are now started
3847 // up.
3848 final int NP = mProcessesOnHold.size();
3849 if (NP > 0) {
3850 ArrayList<ProcessRecord> procs =
3851 new ArrayList<ProcessRecord>(mProcessesOnHold);
3852 for (int ip=0; ip<NP; ip++) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003853 if (DEBUG_PROCESSES) Slog.v(TAG, "Starting process on hold: "
3854 + procs.get(ip));
3855 startProcessLocked(procs.get(ip), "on-hold", null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003856 }
3857 }
3858
3859 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07003860 // Start looking for apps that are abusing wake locks.
3861 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07003862 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003863 // Tell anyone interested that we are done booting!
Dianne Hackbornf4c454b2010-08-11 12:47:41 -07003864 SystemProperties.set("sys.boot_completed", "1");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003865 broadcastIntentLocked(null, null,
3866 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
3867 null, null, 0, null, null,
3868 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
3869 false, false, MY_PID, Process.SYSTEM_UID);
3870 }
3871 }
3872 }
3873
3874 final void ensureBootCompleted() {
3875 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003876 boolean enableScreen;
3877 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003878 booting = mBooting;
3879 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003880 enableScreen = !mBooted;
3881 mBooted = true;
3882 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003883
3884 if (booting) {
3885 finishBooting();
3886 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003887
3888 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003889 enableScreenAfterBoot();
3890 }
3891 }
3892
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08003893 public final void activityPaused(IBinder token) {
3894 final long origId = Binder.clearCallingIdentity();
3895 mMainStack.activityPaused(token, false);
3896 Binder.restoreCallingIdentity(origId);
3897 }
3898
3899 public final void activityStopped(IBinder token, Bundle icicle, Bitmap thumbnail,
3900 CharSequence description) {
3901 if (localLOGV) Slog.v(
3902 TAG, "Activity stopped: token=" + token);
3903
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003904 // Refuse possible leaked file descriptors
3905 if (icicle != null && icicle.hasFileDescriptors()) {
3906 throw new IllegalArgumentException("File descriptors passed in Bundle");
3907 }
3908
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003909 ActivityRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003910
3911 final long origId = Binder.clearCallingIdentity();
3912
3913 synchronized (this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07003914 r = mMainStack.isInStackLocked(token);
3915 if (r != null) {
3916 r.stack.activityStoppedLocked(r, icicle, thumbnail, description);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003917 }
3918 }
3919
3920 if (r != null) {
3921 sendPendingThumbnail(r, null, null, null, false);
3922 }
3923
3924 trimApplications();
3925
3926 Binder.restoreCallingIdentity(origId);
3927 }
3928
3929 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003930 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003931 mMainStack.activityDestroyed(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003932 }
3933
3934 public String getCallingPackage(IBinder token) {
3935 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003936 ActivityRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07003937 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003938 }
3939 }
3940
3941 public ComponentName getCallingActivity(IBinder token) {
3942 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003943 ActivityRecord r = getCallingRecordLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003944 return r != null ? r.intent.getComponent() : null;
3945 }
3946 }
3947
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003948 private ActivityRecord getCallingRecordLocked(IBinder token) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07003949 ActivityRecord r = mMainStack.isInStackLocked(token);
3950 if (r == null) {
3951 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003952 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -07003953 return r.resultTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003954 }
3955
3956 public ComponentName getActivityClassForToken(IBinder token) {
3957 synchronized(this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07003958 ActivityRecord r = mMainStack.isInStackLocked(token);
3959 if (r == null) {
3960 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003961 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -07003962 return r.intent.getComponent();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003963 }
3964 }
3965
3966 public String getPackageForToken(IBinder token) {
3967 synchronized(this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07003968 ActivityRecord r = mMainStack.isInStackLocked(token);
3969 if (r == null) {
3970 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003971 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -07003972 return r.packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003973 }
3974 }
3975
3976 public IIntentSender getIntentSender(int type,
3977 String packageName, IBinder token, String resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003978 int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003979 // Refuse possible leaked file descriptors
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003980 if (intents != null) {
3981 if (intents.length < 1) {
3982 throw new IllegalArgumentException("Intents array length must be >= 1");
3983 }
3984 for (int i=0; i<intents.length; i++) {
3985 Intent intent = intents[i];
Dianne Hackborn52b0ce02011-04-14 13:09:32 -07003986 if (intent != null) {
3987 if (intent.hasFileDescriptors()) {
3988 throw new IllegalArgumentException("File descriptors passed in Intent");
3989 }
3990 if (type == INTENT_SENDER_BROADCAST &&
3991 (intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
3992 throw new IllegalArgumentException(
3993 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
3994 }
3995 intents[i] = new Intent(intent);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003996 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003997 }
3998 if (resolvedTypes != null && resolvedTypes.length != intents.length) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003999 throw new IllegalArgumentException(
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004000 "Intent array length does not match resolvedTypes length");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07004001 }
4002 }
4003
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004004 synchronized(this) {
4005 int callingUid = Binder.getCallingUid();
4006 try {
Jeff Brown10e89712011-07-08 18:52:57 -07004007 if (callingUid != 0 && callingUid != Process.SYSTEM_UID) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004008 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004009 .getPackageUid(packageName);
4010 if (uid != Binder.getCallingUid()) {
4011 String msg = "Permission Denial: getIntentSender() from pid="
4012 + Binder.getCallingPid()
4013 + ", uid=" + Binder.getCallingUid()
4014 + ", (need uid=" + uid + ")"
4015 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004016 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004017 throw new SecurityException(msg);
4018 }
4019 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004020
4021 return getIntentSenderLocked(type, packageName, callingUid,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004022 token, resultWho, requestCode, intents, resolvedTypes, flags);
Dianne Hackborn860755f2010-06-03 18:47:52 -07004023
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004024 } catch (RemoteException e) {
4025 throw new SecurityException(e);
4026 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004027 }
4028 }
4029
4030 IIntentSender getIntentSenderLocked(int type,
4031 String packageName, int callingUid, IBinder token, String resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004032 int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004033 ActivityRecord activity = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004034 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004035 activity = mMainStack.isInStackLocked(token);
4036 if (activity == null) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07004037 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004038 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004039 if (activity.finishing) {
4040 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004041 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004042 }
4043
4044 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
4045 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
4046 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
4047 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
4048 |PendingIntent.FLAG_UPDATE_CURRENT);
4049
4050 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
4051 type, packageName, activity, resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004052 requestCode, intents, resolvedTypes, flags);
Dianne Hackborn860755f2010-06-03 18:47:52 -07004053 WeakReference<PendingIntentRecord> ref;
4054 ref = mIntentSenderRecords.get(key);
4055 PendingIntentRecord rec = ref != null ? ref.get() : null;
4056 if (rec != null) {
4057 if (!cancelCurrent) {
4058 if (updateCurrent) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004059 if (rec.key.requestIntent != null) {
4060 rec.key.requestIntent.replaceExtras(intents != null ? intents[0] : null);
4061 }
4062 if (intents != null) {
4063 intents[intents.length-1] = rec.key.requestIntent;
4064 rec.key.allIntents = intents;
4065 rec.key.allResolvedTypes = resolvedTypes;
4066 } else {
4067 rec.key.allIntents = null;
4068 rec.key.allResolvedTypes = null;
4069 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004070 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004071 return rec;
4072 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004073 rec.canceled = true;
4074 mIntentSenderRecords.remove(key);
4075 }
4076 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004077 return rec;
4078 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004079 rec = new PendingIntentRecord(this, key, callingUid);
4080 mIntentSenderRecords.put(key, rec.ref);
4081 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
4082 if (activity.pendingResults == null) {
4083 activity.pendingResults
4084 = new HashSet<WeakReference<PendingIntentRecord>>();
4085 }
4086 activity.pendingResults.add(rec.ref);
4087 }
4088 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004089 }
4090
4091 public void cancelIntentSender(IIntentSender sender) {
4092 if (!(sender instanceof PendingIntentRecord)) {
4093 return;
4094 }
4095 synchronized(this) {
4096 PendingIntentRecord rec = (PendingIntentRecord)sender;
4097 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004098 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004099 .getPackageUid(rec.key.packageName);
4100 if (uid != Binder.getCallingUid()) {
4101 String msg = "Permission Denial: cancelIntentSender() from pid="
4102 + Binder.getCallingPid()
4103 + ", uid=" + Binder.getCallingUid()
4104 + " is not allowed to cancel packges "
4105 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004106 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004107 throw new SecurityException(msg);
4108 }
4109 } catch (RemoteException e) {
4110 throw new SecurityException(e);
4111 }
4112 cancelIntentSenderLocked(rec, true);
4113 }
4114 }
4115
4116 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
4117 rec.canceled = true;
4118 mIntentSenderRecords.remove(rec.key);
4119 if (cleanActivity && rec.key.activity != null) {
4120 rec.key.activity.pendingResults.remove(rec.ref);
4121 }
4122 }
4123
4124 public String getPackageForIntentSender(IIntentSender pendingResult) {
4125 if (!(pendingResult instanceof PendingIntentRecord)) {
4126 return null;
4127 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07004128 try {
4129 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
4130 return res.key.packageName;
4131 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004132 }
4133 return null;
4134 }
4135
Dianne Hackborn6c418d52011-06-29 14:05:33 -07004136 public boolean isIntentSenderTargetedToPackage(IIntentSender pendingResult) {
4137 if (!(pendingResult instanceof PendingIntentRecord)) {
4138 return false;
4139 }
4140 try {
4141 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
4142 if (res.key.allIntents == null) {
4143 return false;
4144 }
4145 for (int i=0; i<res.key.allIntents.length; i++) {
4146 Intent intent = res.key.allIntents[i];
4147 if (intent.getPackage() != null && intent.getComponent() != null) {
4148 return false;
4149 }
4150 }
4151 return true;
4152 } catch (ClassCastException e) {
4153 }
4154 return false;
4155 }
4156
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004157 public void setProcessLimit(int max) {
4158 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4159 "setProcessLimit()");
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004160 synchronized (this) {
4161 mProcessLimit = max < 0 ? MAX_HIDDEN_APPS : max;
4162 mProcessLimitOverride = max;
4163 }
4164 trimApplications();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004165 }
4166
4167 public int getProcessLimit() {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004168 synchronized (this) {
4169 return mProcessLimitOverride;
4170 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004171 }
4172
4173 void foregroundTokenDied(ForegroundToken token) {
4174 synchronized (ActivityManagerService.this) {
4175 synchronized (mPidsSelfLocked) {
4176 ForegroundToken cur
4177 = mForegroundProcesses.get(token.pid);
4178 if (cur != token) {
4179 return;
4180 }
4181 mForegroundProcesses.remove(token.pid);
4182 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
4183 if (pr == null) {
4184 return;
4185 }
4186 pr.forcingToForeground = null;
4187 pr.foregroundServices = false;
4188 }
4189 updateOomAdjLocked();
4190 }
4191 }
4192
4193 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
4194 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4195 "setProcessForeground()");
4196 synchronized(this) {
4197 boolean changed = false;
4198
4199 synchronized (mPidsSelfLocked) {
4200 ProcessRecord pr = mPidsSelfLocked.get(pid);
4201 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004202 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004203 return;
4204 }
4205 ForegroundToken oldToken = mForegroundProcesses.get(pid);
4206 if (oldToken != null) {
4207 oldToken.token.unlinkToDeath(oldToken, 0);
4208 mForegroundProcesses.remove(pid);
4209 pr.forcingToForeground = null;
4210 changed = true;
4211 }
4212 if (isForeground && token != null) {
4213 ForegroundToken newToken = new ForegroundToken() {
4214 public void binderDied() {
4215 foregroundTokenDied(this);
4216 }
4217 };
4218 newToken.pid = pid;
4219 newToken.token = token;
4220 try {
4221 token.linkToDeath(newToken, 0);
4222 mForegroundProcesses.put(pid, newToken);
4223 pr.forcingToForeground = token;
4224 changed = true;
4225 } catch (RemoteException e) {
4226 // If the process died while doing this, we will later
4227 // do the cleanup with the process death link.
4228 }
4229 }
4230 }
4231
4232 if (changed) {
4233 updateOomAdjLocked();
4234 }
4235 }
4236 }
4237
4238 // =========================================================
4239 // PERMISSIONS
4240 // =========================================================
4241
4242 static class PermissionController extends IPermissionController.Stub {
4243 ActivityManagerService mActivityManagerService;
4244 PermissionController(ActivityManagerService activityManagerService) {
4245 mActivityManagerService = activityManagerService;
4246 }
4247
4248 public boolean checkPermission(String permission, int pid, int uid) {
4249 return mActivityManagerService.checkPermission(permission, pid,
4250 uid) == PackageManager.PERMISSION_GRANTED;
4251 }
4252 }
4253
4254 /**
4255 * This can be called with or without the global lock held.
4256 */
4257 int checkComponentPermission(String permission, int pid, int uid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004258 int owningUid, boolean exported) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004259 // We might be performing an operation on behalf of an indirect binder
4260 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
4261 // client identity accordingly before proceeding.
4262 Identity tlsIdentity = sCallerIdentity.get();
4263 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004264 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004265 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
4266 uid = tlsIdentity.uid;
4267 pid = tlsIdentity.pid;
4268 }
4269
4270 // Root, system server and our own process get to do everything.
Jeff Brown10e89712011-07-08 18:52:57 -07004271 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004272 return PackageManager.PERMISSION_GRANTED;
4273 }
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004274 // If there is a uid that owns whatever is being accessed, it has
4275 // blanket access to it regardless of the permissions it requires.
4276 if (owningUid >= 0 && uid == owningUid) {
4277 return PackageManager.PERMISSION_GRANTED;
4278 }
4279 // If the target is not exported, then nobody else can get to it.
4280 if (!exported) {
4281 Slog.w(TAG, "Permission denied: checkComponentPermission() owningUid=" + owningUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004282 return PackageManager.PERMISSION_DENIED;
4283 }
4284 if (permission == null) {
4285 return PackageManager.PERMISSION_GRANTED;
4286 }
4287 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004288 return AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004289 .checkUidPermission(permission, uid);
4290 } catch (RemoteException e) {
4291 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004292 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004293 }
4294 return PackageManager.PERMISSION_DENIED;
4295 }
4296
4297 /**
4298 * As the only public entry point for permissions checking, this method
4299 * can enforce the semantic that requesting a check on a null global
4300 * permission is automatically denied. (Internally a null permission
4301 * string is used when calling {@link #checkComponentPermission} in cases
4302 * when only uid-based security is needed.)
4303 *
4304 * This can be called with or without the global lock held.
4305 */
4306 public int checkPermission(String permission, int pid, int uid) {
4307 if (permission == null) {
4308 return PackageManager.PERMISSION_DENIED;
4309 }
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004310 return checkComponentPermission(permission, pid, uid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004311 }
4312
4313 /**
4314 * Binder IPC calls go through the public entry point.
4315 * This can be called with or without the global lock held.
4316 */
4317 int checkCallingPermission(String permission) {
4318 return checkPermission(permission,
4319 Binder.getCallingPid(),
4320 Binder.getCallingUid());
4321 }
4322
4323 /**
4324 * This can be called with or without the global lock held.
4325 */
4326 void enforceCallingPermission(String permission, String func) {
4327 if (checkCallingPermission(permission)
4328 == PackageManager.PERMISSION_GRANTED) {
4329 return;
4330 }
4331
4332 String msg = "Permission Denial: " + func + " from pid="
4333 + Binder.getCallingPid()
4334 + ", uid=" + Binder.getCallingUid()
4335 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004336 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004337 throw new SecurityException(msg);
4338 }
4339
4340 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
Dianne Hackborn48058e82010-09-27 16:53:23 -07004341 ProviderInfo pi, Uri uri, int uid, int modeFlags) {
4342 boolean readPerm = (modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0;
4343 boolean writePerm = (modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0;
4344 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4345 "checkHoldingPermissionsLocked: uri=" + uri + " uid=" + uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004346 try {
Dianne Hackborn48058e82010-09-27 16:53:23 -07004347 // Is the component private from the target uid?
4348 final boolean prv = !pi.exported && pi.applicationInfo.uid != uid;
4349
4350 // Acceptable if the there is no read permission needed from the
4351 // target or the target is holding the read permission.
4352 if (!readPerm) {
4353 if ((!prv && pi.readPermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004354 (pm.checkUidPermission(pi.readPermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004355 == PackageManager.PERMISSION_GRANTED)) {
4356 readPerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004357 }
4358 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004359
4360 // Acceptable if the there is no write permission needed from the
4361 // target or the target is holding the read permission.
4362 if (!writePerm) {
4363 if (!prv && (pi.writePermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004364 (pm.checkUidPermission(pi.writePermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004365 == PackageManager.PERMISSION_GRANTED)) {
4366 writePerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004367 }
4368 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004369
4370 // Acceptable if there is a path permission matching the URI that
4371 // the target holds the permission on.
4372 PathPermission[] pps = pi.pathPermissions;
4373 if (pps != null && (!readPerm || !writePerm)) {
4374 final String path = uri.getPath();
4375 int i = pps.length;
4376 while (i > 0 && (!readPerm || !writePerm)) {
4377 i--;
4378 PathPermission pp = pps[i];
4379 if (!readPerm) {
4380 final String pprperm = pp.getReadPermission();
4381 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking read perm for "
4382 + pprperm + " for " + pp.getPath()
4383 + ": match=" + pp.match(path)
4384 + " check=" + pm.checkUidPermission(pprperm, uid));
4385 if (pprperm != null && pp.match(path) &&
4386 (pm.checkUidPermission(pprperm, uid)
4387 == PackageManager.PERMISSION_GRANTED)) {
4388 readPerm = true;
4389 }
4390 }
4391 if (!writePerm) {
4392 final String ppwperm = pp.getWritePermission();
4393 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking write perm "
4394 + ppwperm + " for " + pp.getPath()
4395 + ": match=" + pp.match(path)
4396 + " check=" + pm.checkUidPermission(ppwperm, uid));
4397 if (ppwperm != null && pp.match(path) &&
4398 (pm.checkUidPermission(ppwperm, uid)
4399 == PackageManager.PERMISSION_GRANTED)) {
4400 writePerm = true;
4401 }
4402 }
4403 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004404 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004405 } catch (RemoteException e) {
4406 return false;
4407 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004408
4409 return readPerm && writePerm;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004410 }
4411
4412 private final boolean checkUriPermissionLocked(Uri uri, int uid,
4413 int modeFlags) {
4414 // Root gets to do everything.
Jeff Brown10e89712011-07-08 18:52:57 -07004415 if (uid == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004416 return true;
4417 }
4418 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
4419 if (perms == null) return false;
4420 UriPermission perm = perms.get(uri);
4421 if (perm == null) return false;
4422 return (modeFlags&perm.modeFlags) == modeFlags;
4423 }
4424
4425 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
4426 // Another redirected-binder-call permissions check as in
4427 // {@link checkComponentPermission}.
4428 Identity tlsIdentity = sCallerIdentity.get();
4429 if (tlsIdentity != null) {
4430 uid = tlsIdentity.uid;
4431 pid = tlsIdentity.pid;
4432 }
4433
4434 // Our own process gets to do everything.
4435 if (pid == MY_PID) {
4436 return PackageManager.PERMISSION_GRANTED;
4437 }
4438 synchronized(this) {
4439 return checkUriPermissionLocked(uri, uid, modeFlags)
4440 ? PackageManager.PERMISSION_GRANTED
4441 : PackageManager.PERMISSION_DENIED;
4442 }
4443 }
4444
Dianne Hackborn39792d22010-08-19 18:01:52 -07004445 /**
4446 * Check if the targetPkg can be granted permission to access uri by
4447 * the callingUid using the given modeFlags. Throws a security exception
4448 * if callingUid is not allowed to do this. Returns the uid of the target
4449 * if the URI permission grant should be performed; returns -1 if it is not
4450 * needed (for example targetPkg already has permission to access the URI).
4451 */
4452 int checkGrantUriPermissionLocked(int callingUid, String targetPkg,
4453 Uri uri, int modeFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004454 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4455 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4456 if (modeFlags == 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004457 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004458 }
4459
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004460 if (targetPkg != null) {
4461 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4462 "Checking grant " + targetPkg + " permission to " + uri);
4463 }
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004464
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004465 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004466
4467 // If this is not a content: uri, we can't do anything with it.
4468 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004469 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004470 "Can't grant URI permission for non-content URI: " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004471 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004472 }
4473
4474 String name = uri.getAuthority();
4475 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004476 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004477 if (cpr != null) {
4478 pi = cpr.info;
4479 } else {
4480 try {
4481 pi = pm.resolveContentProvider(name,
4482 PackageManager.GET_URI_PERMISSION_PATTERNS);
4483 } catch (RemoteException ex) {
4484 }
4485 }
4486 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004487 Slog.w(TAG, "No content provider found for: " + name);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004488 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004489 }
4490
4491 int targetUid;
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004492 if (targetPkg != null) {
4493 try {
4494 targetUid = pm.getPackageUid(targetPkg);
4495 if (targetUid < 0) {
4496 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4497 "Can't grant URI permission no uid for: " + targetPkg);
4498 return -1;
4499 }
4500 } catch (RemoteException ex) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004501 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004502 }
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004503 } else {
4504 targetUid = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004505 }
4506
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004507 if (targetUid >= 0) {
4508 // First... does the target actually need this permission?
4509 if (checkHoldingPermissionsLocked(pm, pi, uri, targetUid, modeFlags)) {
4510 // No need to grant the target this permission.
4511 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4512 "Target " + targetPkg + " already has full permission to " + uri);
4513 return -1;
4514 }
4515 } else {
4516 // First... there is no target package, so can anyone access it?
4517 boolean allowed = pi.exported;
4518 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4519 if (pi.readPermission != null) {
4520 allowed = false;
4521 }
4522 }
4523 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4524 if (pi.writePermission != null) {
4525 allowed = false;
4526 }
4527 }
4528 if (allowed) {
4529 return -1;
4530 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004531 }
4532
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004533 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004534 if (!pi.grantUriPermissions) {
4535 throw new SecurityException("Provider " + pi.packageName
4536 + "/" + pi.name
4537 + " does not allow granting of Uri permissions (uri "
4538 + uri + ")");
4539 }
4540 if (pi.uriPermissionPatterns != null) {
4541 final int N = pi.uriPermissionPatterns.length;
4542 boolean allowed = false;
4543 for (int i=0; i<N; i++) {
4544 if (pi.uriPermissionPatterns[i] != null
4545 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
4546 allowed = true;
4547 break;
4548 }
4549 }
4550 if (!allowed) {
4551 throw new SecurityException("Provider " + pi.packageName
4552 + "/" + pi.name
4553 + " does not allow granting of permission to path of Uri "
4554 + uri);
4555 }
4556 }
4557
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004558 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004559 // this uri?
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004560 if (callingUid != Process.myUid()) {
4561 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
4562 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4563 throw new SecurityException("Uid " + callingUid
4564 + " does not have permission to uri " + uri);
4565 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004566 }
4567 }
4568
Dianne Hackborn39792d22010-08-19 18:01:52 -07004569 return targetUid;
4570 }
4571
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004572 public int checkGrantUriPermission(int callingUid, String targetPkg,
4573 Uri uri, int modeFlags) {
4574 synchronized(this) {
4575 return checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4576 }
4577 }
4578
Dianne Hackborn39792d22010-08-19 18:01:52 -07004579 void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg,
4580 Uri uri, int modeFlags, UriPermissionOwner owner) {
4581 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4582 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4583 if (modeFlags == 0) {
4584 return;
4585 }
4586
4587 // So here we are: the caller has the assumed permission
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004588 // to the uri, and the target doesn't. Let's now give this to
4589 // the target.
4590
Joe Onorato8a9b2202010-02-26 18:56:32 -08004591 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004592 "Granting " + targetPkg + "/" + targetUid + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004593
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004594 HashMap<Uri, UriPermission> targetUris
4595 = mGrantedUriPermissions.get(targetUid);
4596 if (targetUris == null) {
4597 targetUris = new HashMap<Uri, UriPermission>();
4598 mGrantedUriPermissions.put(targetUid, targetUris);
4599 }
4600
4601 UriPermission perm = targetUris.get(uri);
4602 if (perm == null) {
4603 perm = new UriPermission(targetUid, uri);
4604 targetUris.put(uri, perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004605 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004606
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004607 perm.modeFlags |= modeFlags;
Dianne Hackborn39792d22010-08-19 18:01:52 -07004608 if (owner == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004609 perm.globalModeFlags |= modeFlags;
Vairavan Srinivasan91c12c22011-01-21 18:26:06 -08004610 } else {
4611 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4612 perm.readOwners.add(owner);
4613 owner.addReadPermission(perm);
4614 }
4615 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4616 perm.writeOwners.add(owner);
4617 owner.addWritePermission(perm);
4618 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004619 }
4620 }
4621
Dianne Hackborn39792d22010-08-19 18:01:52 -07004622 void grantUriPermissionLocked(int callingUid,
4623 String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) {
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004624 if (targetPkg == null) {
4625 throw new NullPointerException("targetPkg");
4626 }
4627
Dianne Hackborn39792d22010-08-19 18:01:52 -07004628 int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4629 if (targetUid < 0) {
4630 return;
4631 }
4632
4633 grantUriPermissionUncheckedLocked(targetUid, targetPkg, uri, modeFlags, owner);
4634 }
4635
4636 /**
4637 * Like checkGrantUriPermissionLocked, but takes an Intent.
4638 */
4639 int checkGrantUriPermissionFromIntentLocked(int callingUid,
4640 String targetPkg, Intent intent) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07004641 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004642 "Checking URI perm to " + (intent != null ? intent.getData() : null)
Dianne Hackbornb424b632010-08-18 15:59:05 -07004643 + " from " + intent + "; flags=0x"
4644 + Integer.toHexString(intent != null ? intent.getFlags() : 0));
4645
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004646 if (targetPkg == null) {
4647 throw new NullPointerException("targetPkg");
4648 }
4649
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004650 if (intent == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004651 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004652 }
4653 Uri data = intent.getData();
4654 if (data == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004655 return -1;
4656 }
4657 return checkGrantUriPermissionLocked(callingUid, targetPkg, data,
4658 intent.getFlags());
4659 }
4660
4661 /**
4662 * Like grantUriPermissionUncheckedLocked, but takes an Intent.
4663 */
4664 void grantUriPermissionUncheckedFromIntentLocked(int targetUid,
4665 String targetPkg, Intent intent, UriPermissionOwner owner) {
4666 grantUriPermissionUncheckedLocked(targetUid, targetPkg, intent.getData(),
4667 intent.getFlags(), owner);
4668 }
4669
4670 void grantUriPermissionFromIntentLocked(int callingUid,
4671 String targetPkg, Intent intent, UriPermissionOwner owner) {
4672 int targetUid = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg, intent);
4673 if (targetUid < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004674 return;
4675 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07004676
4677 grantUriPermissionUncheckedFromIntentLocked(targetUid, targetPkg, intent, owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004678 }
4679
4680 public void grantUriPermission(IApplicationThread caller, String targetPkg,
4681 Uri uri, int modeFlags) {
4682 synchronized(this) {
4683 final ProcessRecord r = getRecordForAppLocked(caller);
4684 if (r == null) {
4685 throw new SecurityException("Unable to find app for caller "
4686 + caller
4687 + " when granting permission to uri " + uri);
4688 }
4689 if (targetPkg == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004690 throw new IllegalArgumentException("null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004691 }
4692 if (uri == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004693 throw new IllegalArgumentException("null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004694 }
4695
4696 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
4697 null);
4698 }
4699 }
4700
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004701 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004702 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
4703 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
4704 HashMap<Uri, UriPermission> perms
4705 = mGrantedUriPermissions.get(perm.uid);
4706 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004707 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004708 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004709 perms.remove(perm.uri);
4710 if (perms.size() == 0) {
4711 mGrantedUriPermissions.remove(perm.uid);
4712 }
4713 }
4714 }
4715 }
4716
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004717 private void revokeUriPermissionLocked(int callingUid, Uri uri,
4718 int modeFlags) {
4719 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4720 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4721 if (modeFlags == 0) {
4722 return;
4723 }
4724
Joe Onorato8a9b2202010-02-26 18:56:32 -08004725 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004726 "Revoking all granted permissions to " + uri);
4727
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004728 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004729
4730 final String authority = uri.getAuthority();
4731 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004732 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004733 if (cpr != null) {
4734 pi = cpr.info;
4735 } else {
4736 try {
4737 pi = pm.resolveContentProvider(authority,
4738 PackageManager.GET_URI_PERMISSION_PATTERNS);
4739 } catch (RemoteException ex) {
4740 }
4741 }
4742 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004743 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004744 return;
4745 }
4746
4747 // Does the caller have this permission on the URI?
Dianne Hackborn48058e82010-09-27 16:53:23 -07004748 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004749 // Right now, if you are not the original owner of the permission,
4750 // you are not allowed to revoke it.
4751 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4752 throw new SecurityException("Uid " + callingUid
4753 + " does not have permission to uri " + uri);
4754 //}
4755 }
4756
4757 // Go through all of the permissions and remove any that match.
4758 final List<String> SEGMENTS = uri.getPathSegments();
4759 if (SEGMENTS != null) {
4760 final int NS = SEGMENTS.size();
4761 int N = mGrantedUriPermissions.size();
4762 for (int i=0; i<N; i++) {
4763 HashMap<Uri, UriPermission> perms
4764 = mGrantedUriPermissions.valueAt(i);
4765 Iterator<UriPermission> it = perms.values().iterator();
4766 toploop:
4767 while (it.hasNext()) {
4768 UriPermission perm = it.next();
4769 Uri targetUri = perm.uri;
4770 if (!authority.equals(targetUri.getAuthority())) {
4771 continue;
4772 }
4773 List<String> targetSegments = targetUri.getPathSegments();
4774 if (targetSegments == null) {
4775 continue;
4776 }
4777 if (targetSegments.size() < NS) {
4778 continue;
4779 }
4780 for (int j=0; j<NS; j++) {
4781 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
4782 continue toploop;
4783 }
4784 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004785 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004786 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004787 perm.clearModes(modeFlags);
4788 if (perm.modeFlags == 0) {
4789 it.remove();
4790 }
4791 }
4792 if (perms.size() == 0) {
4793 mGrantedUriPermissions.remove(
4794 mGrantedUriPermissions.keyAt(i));
4795 N--;
4796 i--;
4797 }
4798 }
4799 }
4800 }
4801
4802 public void revokeUriPermission(IApplicationThread caller, Uri uri,
4803 int modeFlags) {
4804 synchronized(this) {
4805 final ProcessRecord r = getRecordForAppLocked(caller);
4806 if (r == null) {
4807 throw new SecurityException("Unable to find app for caller "
4808 + caller
4809 + " when revoking permission to uri " + uri);
4810 }
4811 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004812 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004813 return;
4814 }
4815
4816 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4817 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4818 if (modeFlags == 0) {
4819 return;
4820 }
4821
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004822 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004823
4824 final String authority = uri.getAuthority();
4825 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004826 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004827 if (cpr != null) {
4828 pi = cpr.info;
4829 } else {
4830 try {
4831 pi = pm.resolveContentProvider(authority,
4832 PackageManager.GET_URI_PERMISSION_PATTERNS);
4833 } catch (RemoteException ex) {
4834 }
4835 }
4836 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004837 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004838 return;
4839 }
4840
4841 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
4842 }
4843 }
4844
Dianne Hackborn7e269642010-08-25 19:50:20 -07004845 @Override
4846 public IBinder newUriPermissionOwner(String name) {
4847 synchronized(this) {
4848 UriPermissionOwner owner = new UriPermissionOwner(this, name);
4849 return owner.getExternalTokenLocked();
4850 }
4851 }
4852
4853 @Override
4854 public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg,
4855 Uri uri, int modeFlags) {
4856 synchronized(this) {
4857 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4858 if (owner == null) {
4859 throw new IllegalArgumentException("Unknown owner: " + token);
4860 }
4861 if (fromUid != Binder.getCallingUid()) {
4862 if (Binder.getCallingUid() != Process.myUid()) {
4863 // Only system code can grant URI permissions on behalf
4864 // of other users.
4865 throw new SecurityException("nice try");
4866 }
4867 }
4868 if (targetPkg == null) {
4869 throw new IllegalArgumentException("null target");
4870 }
4871 if (uri == null) {
4872 throw new IllegalArgumentException("null uri");
4873 }
4874
4875 grantUriPermissionLocked(fromUid, targetPkg, uri, modeFlags, owner);
4876 }
4877 }
4878
4879 @Override
4880 public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode) {
4881 synchronized(this) {
4882 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4883 if (owner == null) {
4884 throw new IllegalArgumentException("Unknown owner: " + token);
4885 }
4886
4887 if (uri == null) {
4888 owner.removeUriPermissionsLocked(mode);
4889 } else {
4890 owner.removeUriPermissionLocked(uri, mode);
4891 }
4892 }
4893 }
4894
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004895 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
4896 synchronized (this) {
4897 ProcessRecord app =
4898 who != null ? getRecordForAppLocked(who) : null;
4899 if (app == null) return;
4900
4901 Message msg = Message.obtain();
4902 msg.what = WAIT_FOR_DEBUGGER_MSG;
4903 msg.obj = app;
4904 msg.arg1 = waiting ? 1 : 0;
4905 mHandler.sendMessage(msg);
4906 }
4907 }
4908
4909 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
4910 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08004911 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004912 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08004913 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004914 }
4915
4916 // =========================================================
4917 // TASK MANAGEMENT
4918 // =========================================================
4919
4920 public List getTasks(int maxNum, int flags,
4921 IThumbnailReceiver receiver) {
4922 ArrayList list = new ArrayList();
4923
4924 PendingThumbnailsRecord pending = null;
4925 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004926 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004927
4928 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004929 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004930 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
4931 + ", receiver=" + receiver);
4932
4933 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
4934 != PackageManager.PERMISSION_GRANTED) {
4935 if (receiver != null) {
4936 // If the caller wants to wait for pending thumbnails,
4937 // it ain't gonna get them.
4938 try {
4939 receiver.finished();
4940 } catch (RemoteException ex) {
4941 }
4942 }
4943 String msg = "Permission Denial: getTasks() from pid="
4944 + Binder.getCallingPid()
4945 + ", uid=" + Binder.getCallingUid()
4946 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004947 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004948 throw new SecurityException(msg);
4949 }
4950
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004951 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004952 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004953 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004954 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004955 TaskRecord curTask = null;
4956 int numActivities = 0;
4957 int numRunning = 0;
4958 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004959 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004960 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004961 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004962
4963 // Initialize state for next task if needed.
4964 if (top == null ||
4965 (top.state == ActivityState.INITIALIZING
4966 && top.task == r.task)) {
4967 top = r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004968 curTask = r.task;
4969 numActivities = numRunning = 0;
4970 }
4971
4972 // Add 'r' into the current task.
4973 numActivities++;
4974 if (r.app != null && r.app.thread != null) {
4975 numRunning++;
4976 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004977
Joe Onorato8a9b2202010-02-26 18:56:32 -08004978 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004979 TAG, r.intent.getComponent().flattenToShortString()
4980 + ": task=" + r.task);
4981
4982 // If the next one is a different task, generate a new
4983 // TaskInfo entry for what we have.
4984 if (next == null || next.task != curTask) {
4985 ActivityManager.RunningTaskInfo ci
4986 = new ActivityManager.RunningTaskInfo();
4987 ci.id = curTask.taskId;
4988 ci.baseActivity = r.intent.getComponent();
4989 ci.topActivity = top.intent.getComponent();
Dianne Hackbornf26fd992011-04-08 18:14:09 -07004990 if (top.thumbHolder != null) {
4991 ci.description = top.thumbHolder.lastDescription;
4992 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004993 ci.numActivities = numActivities;
4994 ci.numRunning = numRunning;
4995 //System.out.println(
4996 // "#" + maxNum + ": " + " descr=" + ci.description);
4997 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004998 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004999 TAG, "State=" + top.state + "Idle=" + top.idle
5000 + " app=" + top.app
5001 + " thr=" + (top.app != null ? top.app.thread : null));
5002 if (top.state == ActivityState.RESUMED
5003 || top.state == ActivityState.PAUSING) {
5004 if (top.idle && top.app != null
5005 && top.app.thread != null) {
5006 topRecord = top;
5007 topThumbnail = top.app.thread;
5008 } else {
5009 top.thumbnailNeeded = true;
5010 }
5011 }
5012 if (pending == null) {
5013 pending = new PendingThumbnailsRecord(receiver);
5014 }
5015 pending.pendingRecords.add(top);
5016 }
5017 list.add(ci);
5018 maxNum--;
5019 top = null;
5020 }
5021 }
5022
5023 if (pending != null) {
5024 mPendingThumbnails.add(pending);
5025 }
5026 }
5027
Joe Onorato8a9b2202010-02-26 18:56:32 -08005028 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005029
5030 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005031 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005032 try {
5033 topThumbnail.requestThumbnail(topRecord);
5034 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005035 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005036 sendPendingThumbnail(null, topRecord, null, null, true);
5037 }
5038 }
5039
5040 if (pending == null && receiver != null) {
5041 // In this case all thumbnails were available and the client
5042 // is being asked to be told when the remaining ones come in...
5043 // which is unusually, since the top-most currently running
5044 // activity should never have a canned thumbnail! Oh well.
5045 try {
5046 receiver.finished();
5047 } catch (RemoteException ex) {
5048 }
5049 }
5050
5051 return list;
5052 }
5053
5054 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
5055 int flags) {
5056 synchronized (this) {
5057 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
5058 "getRecentTasks()");
5059
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005060 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07005061
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005062 final int N = mRecentTasks.size();
5063 ArrayList<ActivityManager.RecentTaskInfo> res
5064 = new ArrayList<ActivityManager.RecentTaskInfo>(
5065 maxNum < N ? maxNum : N);
5066 for (int i=0; i<N && maxNum > 0; i++) {
5067 TaskRecord tr = mRecentTasks.get(i);
5068 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
5069 || (tr.intent == null)
5070 || ((tr.intent.getFlags()
5071 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
5072 ActivityManager.RecentTaskInfo rti
5073 = new ActivityManager.RecentTaskInfo();
5074 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
Dianne Hackbornd94df452011-02-16 18:53:31 -08005075 rti.persistentId = tr.taskId;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005076 rti.baseIntent = new Intent(
5077 tr.intent != null ? tr.intent : tr.affinityIntent);
5078 rti.origActivity = tr.origActivity;
Dianne Hackbornd2835932010-12-13 16:28:46 -08005079 rti.description = tr.lastDescription;
5080
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07005081 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
5082 // Check whether this activity is currently available.
5083 try {
5084 if (rti.origActivity != null) {
5085 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
5086 continue;
5087 }
5088 } else if (rti.baseIntent != null) {
5089 if (pm.queryIntentActivities(rti.baseIntent,
5090 null, 0) == null) {
5091 continue;
5092 }
5093 }
5094 } catch (RemoteException e) {
5095 // Will never happen.
5096 }
5097 }
5098
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005099 res.add(rti);
5100 maxNum--;
5101 }
5102 }
5103 return res;
5104 }
5105 }
5106
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005107 private TaskRecord taskForIdLocked(int id) {
5108 final int N = mRecentTasks.size();
5109 for (int i=0; i<N; i++) {
5110 TaskRecord tr = mRecentTasks.get(i);
5111 if (tr.taskId == id) {
5112 return tr;
Dianne Hackbornd94df452011-02-16 18:53:31 -08005113 }
5114 }
5115 return null;
5116 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005117
5118 public ActivityManager.TaskThumbnails getTaskThumbnails(int id) {
5119 synchronized (this) {
5120 enforceCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER,
5121 "getTaskThumbnails()");
5122 TaskRecord tr = taskForIdLocked(id);
5123 if (tr != null) {
5124 return mMainStack.getTaskThumbnailsLocked(tr);
5125 }
5126 }
5127 return null;
5128 }
5129
5130 public boolean removeSubTask(int taskId, int subTaskIndex) {
5131 synchronized (this) {
5132 enforceCallingPermission(android.Manifest.permission.REMOVE_TASKS,
5133 "removeSubTask()");
5134 long ident = Binder.clearCallingIdentity();
5135 try {
5136 return mMainStack.removeTaskActivitiesLocked(taskId, subTaskIndex) != null;
5137 } finally {
5138 Binder.restoreCallingIdentity(ident);
5139 }
5140 }
5141 }
5142
Dianne Hackborn8894cc52011-07-01 16:28:17 -07005143 private void cleanUpRemovedTaskLocked(ActivityRecord root, boolean killProcesses) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005144 TaskRecord tr = root.task;
5145 Intent baseIntent = new Intent(
5146 tr.intent != null ? tr.intent : tr.affinityIntent);
5147 ComponentName component = baseIntent.getComponent();
5148 if (component == null) {
5149 Slog.w(TAG, "Now component for base intent of task: " + tr);
5150 return;
5151 }
5152
5153 // Find any running services associated with this app.
5154 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
5155 for (ServiceRecord sr : mServices.values()) {
5156 if (sr.packageName.equals(component.getPackageName())) {
5157 services.add(sr);
5158 }
5159 }
5160
5161 // Take care of any running services associated with the app.
5162 for (int i=0; i<services.size(); i++) {
5163 ServiceRecord sr = services.get(i);
5164 if (sr.startRequested) {
5165 if ((sr.serviceInfo.flags&ServiceInfo.FLAG_STOP_WITH_TASK) != 0) {
Dianne Hackborn8894cc52011-07-01 16:28:17 -07005166 Slog.i(TAG, "Stopping service " + sr.shortName + ": remove task");
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005167 stopServiceLocked(sr);
5168 } else {
5169 sr.pendingStarts.add(new ServiceRecord.StartItem(sr, true,
5170 sr.makeNextStartId(), baseIntent, -1));
5171 if (sr.app != null && sr.app.thread != null) {
5172 sendServiceArgsLocked(sr, false);
5173 }
5174 }
5175 }
5176 }
5177
Dianne Hackborn8894cc52011-07-01 16:28:17 -07005178 if (killProcesses) {
5179 // Find any running processes associated with this app.
5180 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
5181 SparseArray<ProcessRecord> appProcs
5182 = mProcessNames.getMap().get(component.getPackageName());
5183 if (appProcs != null) {
5184 for (int i=0; i<appProcs.size(); i++) {
5185 procs.add(appProcs.valueAt(i));
5186 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005187 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005188
Dianne Hackborn8894cc52011-07-01 16:28:17 -07005189 // Kill the running processes.
5190 for (int i=0; i<procs.size(); i++) {
5191 ProcessRecord pr = procs.get(i);
5192 if (pr.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {
5193 Slog.i(TAG, "Killing " + pr.toShortString() + ": remove task");
5194 EventLog.writeEvent(EventLogTags.AM_KILL, pr.pid,
5195 pr.processName, pr.setAdj, "remove task");
5196 Process.killProcessQuiet(pr.pid);
5197 } else {
5198 pr.waitingToKill = "remove task";
5199 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005200 }
5201 }
5202 }
5203
5204 public boolean removeTask(int taskId, int flags) {
5205 synchronized (this) {
5206 enforceCallingPermission(android.Manifest.permission.REMOVE_TASKS,
5207 "removeTask()");
5208 long ident = Binder.clearCallingIdentity();
5209 try {
5210 ActivityRecord r = mMainStack.removeTaskActivitiesLocked(taskId, -1);
5211 if (r != null) {
5212 mRecentTasks.remove(r.task);
Dianne Hackborn8894cc52011-07-01 16:28:17 -07005213 cleanUpRemovedTaskLocked(r,
5214 (flags&ActivityManager.REMOVE_TASK_KILL_PROCESS) != 0);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005215 return true;
5216 }
5217 } finally {
5218 Binder.restoreCallingIdentity(ident);
5219 }
5220 }
5221 return false;
5222 }
Dianne Hackbornd94df452011-02-16 18:53:31 -08005223
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005224 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
5225 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005226 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005227 TaskRecord jt = startTask;
5228
5229 // First look backwards
5230 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005231 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005232 if (r.task != jt) {
5233 jt = r.task;
5234 if (affinity.equals(jt.affinity)) {
5235 return j;
5236 }
5237 }
5238 }
5239
5240 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005241 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005242 jt = startTask;
5243 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005244 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005245 if (r.task != jt) {
5246 if (affinity.equals(jt.affinity)) {
5247 return j;
5248 }
5249 jt = r.task;
5250 }
5251 }
5252
5253 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005254 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005255 return N-1;
5256 }
5257
5258 return -1;
5259 }
5260
5261 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005262 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005263 */
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005264 public void moveTaskToFront(int task, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005265 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5266 "moveTaskToFront()");
5267
5268 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005269 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5270 Binder.getCallingUid(), "Task to front")) {
5271 return;
5272 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005273 final long origId = Binder.clearCallingIdentity();
5274 try {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005275 TaskRecord tr = taskForIdLocked(task);
5276 if (tr != null) {
5277 if ((flags&ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
5278 mMainStack.mUserLeaving = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005279 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005280 if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
5281 // Caller wants the home activity moved with it. To accomplish this,
5282 // we'll just move the home task to the top first.
5283 mMainStack.moveHomeToFrontLocked();
5284 }
5285 mMainStack.moveTaskToFrontLocked(tr, null);
5286 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005287 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005288 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
5289 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005290 if (hr.task.taskId == task) {
Dianne Hackbornd94df452011-02-16 18:53:31 -08005291 if ((flags&ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
5292 mMainStack.mUserLeaving = true;
5293 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005294 if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
5295 // Caller wants the home activity moved with it. To accomplish this,
5296 // we'll just move the home task to the top first.
5297 mMainStack.moveHomeToFrontLocked();
5298 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005299 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005300 return;
5301 }
5302 }
5303 } finally {
5304 Binder.restoreCallingIdentity(origId);
5305 }
5306 }
5307 }
5308
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005309 public void moveTaskToBack(int task) {
5310 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5311 "moveTaskToBack()");
5312
5313 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005314 if (mMainStack.mResumedActivity != null
5315 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005316 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5317 Binder.getCallingUid(), "Task to back")) {
5318 return;
5319 }
5320 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005321 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005322 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005323 Binder.restoreCallingIdentity(origId);
5324 }
5325 }
5326
5327 /**
5328 * Moves an activity, and all of the other activities within the same task, to the bottom
5329 * of the history stack. The activity's order within the task is unchanged.
5330 *
5331 * @param token A reference to the activity we wish to move
5332 * @param nonRoot If false then this only works if the activity is the root
5333 * of a task; if true it will work for any activity in a task.
5334 * @return Returns true if the move completed, false if not.
5335 */
5336 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
5337 synchronized(this) {
5338 final long origId = Binder.clearCallingIdentity();
5339 int taskId = getTaskForActivityLocked(token, !nonRoot);
5340 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005341 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005342 }
5343 Binder.restoreCallingIdentity(origId);
5344 }
5345 return false;
5346 }
5347
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005348 public void moveTaskBackwards(int task) {
5349 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5350 "moveTaskBackwards()");
5351
5352 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005353 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5354 Binder.getCallingUid(), "Task backwards")) {
5355 return;
5356 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005357 final long origId = Binder.clearCallingIdentity();
5358 moveTaskBackwardsLocked(task);
5359 Binder.restoreCallingIdentity(origId);
5360 }
5361 }
5362
5363 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005364 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005365 }
5366
5367 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
5368 synchronized(this) {
5369 return getTaskForActivityLocked(token, onlyRoot);
5370 }
5371 }
5372
5373 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005374 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005375 TaskRecord lastTask = null;
5376 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005377 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005378 if (r == token) {
5379 if (!onlyRoot || lastTask != r.task) {
5380 return r.task.taskId;
5381 }
5382 return -1;
5383 }
5384 lastTask = r.task;
5385 }
5386
5387 return -1;
5388 }
5389
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005390 public void finishOtherInstances(IBinder token, ComponentName className) {
5391 synchronized(this) {
5392 final long origId = Binder.clearCallingIdentity();
5393
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005394 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.realActivity.equals(className)
5399 && r != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005400 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005401 null, "others")) {
5402 i--;
5403 N--;
5404 }
5405 }
5406 lastTask = r.task;
5407 }
5408
5409 Binder.restoreCallingIdentity(origId);
5410 }
5411 }
5412
5413 // =========================================================
5414 // THUMBNAILS
5415 // =========================================================
5416
5417 public void reportThumbnail(IBinder token,
5418 Bitmap thumbnail, CharSequence description) {
5419 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
5420 final long origId = Binder.clearCallingIdentity();
5421 sendPendingThumbnail(null, token, thumbnail, description, true);
5422 Binder.restoreCallingIdentity(origId);
5423 }
5424
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005425 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005426 Bitmap thumbnail, CharSequence description, boolean always) {
5427 TaskRecord task = null;
5428 ArrayList receivers = null;
5429
5430 //System.out.println("Send pending thumbnail: " + r);
5431
5432 synchronized(this) {
5433 if (r == null) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07005434 r = mMainStack.isInStackLocked(token);
5435 if (r == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005436 return;
5437 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005438 }
Dianne Hackbornf26fd992011-04-08 18:14:09 -07005439 if (thumbnail == null && r.thumbHolder != null) {
5440 thumbnail = r.thumbHolder.lastThumbnail;
5441 description = r.thumbHolder.lastDescription;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005442 }
5443 if (thumbnail == null && !always) {
5444 // If there is no thumbnail, and this entry is not actually
5445 // going away, then abort for now and pick up the next
5446 // thumbnail we get.
5447 return;
5448 }
5449 task = r.task;
5450
5451 int N = mPendingThumbnails.size();
5452 int i=0;
5453 while (i<N) {
5454 PendingThumbnailsRecord pr =
5455 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
5456 //System.out.println("Looking in " + pr.pendingRecords);
5457 if (pr.pendingRecords.remove(r)) {
5458 if (receivers == null) {
5459 receivers = new ArrayList();
5460 }
5461 receivers.add(pr);
5462 if (pr.pendingRecords.size() == 0) {
5463 pr.finished = true;
5464 mPendingThumbnails.remove(i);
5465 N--;
5466 continue;
5467 }
5468 }
5469 i++;
5470 }
5471 }
5472
5473 if (receivers != null) {
5474 final int N = receivers.size();
5475 for (int i=0; i<N; i++) {
5476 try {
5477 PendingThumbnailsRecord pr =
5478 (PendingThumbnailsRecord)receivers.get(i);
5479 pr.receiver.newThumbnail(
5480 task != null ? task.taskId : -1, thumbnail, description);
5481 if (pr.finished) {
5482 pr.receiver.finished();
5483 }
5484 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005485 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005486 }
5487 }
5488 }
5489 }
5490
5491 // =========================================================
5492 // CONTENT PROVIDERS
5493 // =========================================================
5494
Jeff Brown10e89712011-07-08 18:52:57 -07005495 private final List<ProviderInfo> generateApplicationProvidersLocked(ProcessRecord app) {
5496 List<ProviderInfo> providers = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005497 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005498 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005499 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005500 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005501 } catch (RemoteException ex) {
5502 }
5503 if (providers != null) {
5504 final int N = providers.size();
5505 for (int i=0; i<N; i++) {
5506 ProviderInfo cpi =
5507 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005508 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005509 if (cpr == null) {
5510 cpr = new ContentProviderRecord(cpi, app.info);
5511 mProvidersByClass.put(cpi.name, cpr);
5512 }
5513 app.pubProviders.put(cpi.name, cpr);
5514 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005515 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005516 }
5517 }
5518 return providers;
5519 }
5520
5521 private final String checkContentProviderPermissionLocked(
Dianne Hackbornb424b632010-08-18 15:59:05 -07005522 ProviderInfo cpi, ProcessRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005523 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
5524 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
5525 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005526 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005527 == PackageManager.PERMISSION_GRANTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005528 return null;
5529 }
5530 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005531 cpi.applicationInfo.uid, cpi.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005532 == PackageManager.PERMISSION_GRANTED) {
5533 return null;
5534 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005535
5536 PathPermission[] pps = cpi.pathPermissions;
5537 if (pps != null) {
5538 int i = pps.length;
5539 while (i > 0) {
5540 i--;
5541 PathPermission pp = pps[i];
5542 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005543 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005544 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005545 return null;
5546 }
5547 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005548 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005549 == PackageManager.PERMISSION_GRANTED) {
5550 return null;
5551 }
5552 }
5553 }
5554
Dianne Hackbornb424b632010-08-18 15:59:05 -07005555 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
5556 if (perms != null) {
5557 for (Map.Entry<Uri, UriPermission> uri : perms.entrySet()) {
5558 if (uri.getKey().getAuthority().equals(cpi.authority)) {
5559 return null;
5560 }
5561 }
5562 }
5563
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005564 String msg;
5565 if (!cpi.exported) {
5566 msg = "Permission Denial: opening provider " + cpi.name
5567 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5568 + ", uid=" + callingUid + ") that is not exported from uid "
5569 + cpi.applicationInfo.uid;
5570 } else {
5571 msg = "Permission Denial: opening provider " + cpi.name
5572 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5573 + ", uid=" + callingUid + ") requires "
5574 + cpi.readPermission + " or " + cpi.writePermission;
5575 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005576 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005577 return msg;
5578 }
5579
5580 private final ContentProviderHolder getContentProviderImpl(
5581 IApplicationThread caller, String name) {
5582 ContentProviderRecord cpr;
5583 ProviderInfo cpi = null;
5584
5585 synchronized(this) {
5586 ProcessRecord r = null;
5587 if (caller != null) {
5588 r = getRecordForAppLocked(caller);
5589 if (r == null) {
5590 throw new SecurityException(
5591 "Unable to find app for caller " + caller
5592 + " (pid=" + Binder.getCallingPid()
5593 + ") when getting content provider " + name);
5594 }
5595 }
5596
5597 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07005598 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005599 if (cpr != null) {
5600 cpi = cpr.info;
Dianne Hackbornb424b632010-08-18 15:59:05 -07005601 String msg;
5602 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5603 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005604 }
5605
5606 if (r != null && cpr.canRunHere(r)) {
5607 // This provider has been published or is in the process
5608 // of being published... but it is also allowed to run
5609 // in the caller's process, so don't make a connection
5610 // and just let the caller instantiate its own instance.
5611 if (cpr.provider != null) {
5612 // don't give caller the provider object, it needs
5613 // to make its own.
5614 cpr = new ContentProviderRecord(cpr);
5615 }
5616 return cpr;
5617 }
5618
5619 final long origId = Binder.clearCallingIdentity();
5620
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005621 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005622 // return it right away.
5623 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005624 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005625 "Adding provider requested by "
5626 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005627 + cpr.info.processName);
5628 Integer cnt = r.conProviders.get(cpr);
5629 if (cnt == null) {
5630 r.conProviders.put(cpr, new Integer(1));
5631 } else {
5632 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5633 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005634 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07005635 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
5636 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07005637 // make sure to count it as being accessed and thus
5638 // back up on the LRU list. This is good because
5639 // content providers are often expensive to start.
5640 updateLruProcessLocked(cpr.app, false, true);
5641 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07005642 } else {
5643 cpr.externals++;
5644 }
5645
5646 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005647 updateOomAdjLocked(cpr.app);
5648 }
5649
5650 Binder.restoreCallingIdentity(origId);
5651
5652 } else {
5653 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005654 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005655 resolveContentProvider(name,
5656 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005657 } catch (RemoteException ex) {
5658 }
5659 if (cpi == null) {
5660 return null;
5661 }
5662
Dianne Hackbornb424b632010-08-18 15:59:05 -07005663 String msg;
5664 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5665 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005666 }
5667
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07005668 if (!mProcessesReady && !mDidUpdate && !mWaitingUpdate
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005669 && !cpi.processName.equals("system")) {
5670 // If this content provider does not run in the system
5671 // process, and the system is not yet ready to run other
5672 // processes, then fail fast instead of hanging.
5673 throw new IllegalArgumentException(
5674 "Attempt to launch content provider before system ready");
5675 }
5676
Dianne Hackborn860755f2010-06-03 18:47:52 -07005677 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005678 final boolean firstClass = cpr == null;
5679 if (firstClass) {
5680 try {
5681 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005682 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005683 getApplicationInfo(
5684 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005685 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005686 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005687 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005688 + cpi.name);
5689 return null;
5690 }
5691 cpr = new ContentProviderRecord(cpi, ai);
5692 } catch (RemoteException ex) {
5693 // pm is in same process, this will never happen.
5694 }
5695 }
5696
5697 if (r != null && cpr.canRunHere(r)) {
5698 // If this is a multiprocess provider, then just return its
5699 // info and allow the caller to instantiate it. Only do
5700 // this if the provider is the same user as the caller's
5701 // process, or can run as root (so can be in any process).
5702 return cpr;
5703 }
5704
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005705 if (DEBUG_PROVIDER) {
5706 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08005707 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005708 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005709 }
5710
5711 // This is single process, and our app is now connecting to it.
5712 // See if we are already in the process of launching this
5713 // provider.
5714 final int N = mLaunchingProviders.size();
5715 int i;
5716 for (i=0; i<N; i++) {
5717 if (mLaunchingProviders.get(i) == cpr) {
5718 break;
5719 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005720 }
5721
5722 // If the provider is not already being launched, then get it
5723 // started.
5724 if (i >= N) {
5725 final long origId = Binder.clearCallingIdentity();
Dianne Hackborne7f97212011-02-24 14:40:20 -08005726
5727 try {
5728 // Content provider is now in use, its package can't be stopped.
5729 try {
5730 AppGlobals.getPackageManager().setPackageStoppedState(
5731 cpr.appInfo.packageName, false);
5732 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08005733 } catch (IllegalArgumentException e) {
5734 Slog.w(TAG, "Failed trying to unstop package "
5735 + cpr.appInfo.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08005736 }
5737
5738 ProcessRecord proc = startProcessLocked(cpi.processName,
5739 cpr.appInfo, false, 0, "content provider",
5740 new ComponentName(cpi.applicationInfo.packageName,
5741 cpi.name), false);
5742 if (proc == null) {
5743 Slog.w(TAG, "Unable to launch app "
5744 + cpi.applicationInfo.packageName + "/"
5745 + cpi.applicationInfo.uid + " for provider "
5746 + name + ": process is bad");
5747 return null;
5748 }
5749 cpr.launchingApp = proc;
5750 mLaunchingProviders.add(cpr);
5751 } finally {
5752 Binder.restoreCallingIdentity(origId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005753 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005754 }
5755
5756 // Make sure the provider is published (the same provider class
5757 // may be published under multiple names).
5758 if (firstClass) {
5759 mProvidersByClass.put(cpi.name, cpr);
5760 }
5761 mProvidersByName.put(name, cpr);
5762
5763 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005764 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005765 "Adding provider requested by "
5766 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005767 + cpr.info.processName);
5768 Integer cnt = r.conProviders.get(cpr);
5769 if (cnt == null) {
5770 r.conProviders.put(cpr, new Integer(1));
5771 } else {
5772 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5773 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005774 cpr.clients.add(r);
5775 } else {
5776 cpr.externals++;
5777 }
5778 }
5779 }
5780
5781 // Wait for the provider to be published...
5782 synchronized (cpr) {
5783 while (cpr.provider == null) {
5784 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005785 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005786 + cpi.applicationInfo.packageName + "/"
5787 + cpi.applicationInfo.uid + " for provider "
5788 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005789 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005790 cpi.applicationInfo.packageName,
5791 cpi.applicationInfo.uid, name);
5792 return null;
5793 }
5794 try {
5795 cpr.wait();
5796 } catch (InterruptedException ex) {
5797 }
5798 }
5799 }
5800 return cpr;
5801 }
5802
5803 public final ContentProviderHolder getContentProvider(
5804 IApplicationThread caller, String name) {
5805 if (caller == null) {
5806 String msg = "null IApplicationThread when getting content provider "
5807 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005808 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005809 throw new SecurityException(msg);
5810 }
5811
5812 return getContentProviderImpl(caller, name);
5813 }
5814
5815 private ContentProviderHolder getContentProviderExternal(String name) {
5816 return getContentProviderImpl(null, name);
5817 }
5818
5819 /**
5820 * Drop a content provider from a ProcessRecord's bookkeeping
5821 * @param cpr
5822 */
5823 public void removeContentProvider(IApplicationThread caller, String name) {
5824 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005825 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005826 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005827 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005828 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005829 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005830 return;
5831 }
5832 final ProcessRecord r = getRecordForAppLocked(caller);
5833 if (r == null) {
5834 throw new SecurityException(
5835 "Unable to find app for caller " + caller +
5836 " when removing content provider " + name);
5837 }
5838 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005839 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005840 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005841 + r.info.processName + " from process "
5842 + localCpr.appInfo.processName);
5843 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005844 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08005845 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005846 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005847 return;
5848 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005849 Integer cnt = r.conProviders.get(localCpr);
5850 if (cnt == null || cnt.intValue() <= 1) {
5851 localCpr.clients.remove(r);
5852 r.conProviders.remove(localCpr);
5853 } else {
5854 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
5855 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005856 }
5857 updateOomAdjLocked();
5858 }
5859 }
5860
5861 private void removeContentProviderExternal(String name) {
5862 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005863 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005864 if(cpr == null) {
5865 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005866 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005867 return;
5868 }
5869
5870 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005871 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005872 localCpr.externals--;
5873 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005874 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005875 }
5876 updateOomAdjLocked();
5877 }
5878 }
5879
5880 public final void publishContentProviders(IApplicationThread caller,
5881 List<ContentProviderHolder> providers) {
5882 if (providers == null) {
5883 return;
5884 }
5885
5886 synchronized(this) {
5887 final ProcessRecord r = getRecordForAppLocked(caller);
5888 if (r == null) {
5889 throw new SecurityException(
5890 "Unable to find app for caller " + caller
5891 + " (pid=" + Binder.getCallingPid()
5892 + ") when publishing content providers");
5893 }
5894
5895 final long origId = Binder.clearCallingIdentity();
5896
5897 final int N = providers.size();
5898 for (int i=0; i<N; i++) {
5899 ContentProviderHolder src = providers.get(i);
5900 if (src == null || src.info == null || src.provider == null) {
5901 continue;
5902 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005903 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005904 if (dst != null) {
5905 mProvidersByClass.put(dst.info.name, dst);
5906 String names[] = dst.info.authority.split(";");
5907 for (int j = 0; j < names.length; j++) {
5908 mProvidersByName.put(names[j], dst);
5909 }
5910
5911 int NL = mLaunchingProviders.size();
5912 int j;
5913 for (j=0; j<NL; j++) {
5914 if (mLaunchingProviders.get(j) == dst) {
5915 mLaunchingProviders.remove(j);
5916 j--;
5917 NL--;
5918 }
5919 }
5920 synchronized (dst) {
5921 dst.provider = src.provider;
5922 dst.app = r;
5923 dst.notifyAll();
5924 }
5925 updateOomAdjLocked(r);
5926 }
5927 }
5928
5929 Binder.restoreCallingIdentity(origId);
5930 }
5931 }
5932
5933 public static final void installSystemProviders() {
Jeff Brown10e89712011-07-08 18:52:57 -07005934 List<ProviderInfo> providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06005935 synchronized (mSelf) {
5936 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
5937 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005938 if (providers != null) {
5939 for (int i=providers.size()-1; i>=0; i--) {
5940 ProviderInfo pi = (ProviderInfo)providers.get(i);
5941 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5942 Slog.w(TAG, "Not installing system proc provider " + pi.name
5943 + ": not system .apk");
5944 providers.remove(i);
5945 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005946 }
5947 }
5948 }
Josh Bartel2ecce342010-02-25 10:55:48 -06005949 if (providers != null) {
5950 mSystemThread.installSystemProviders(providers);
5951 }
Svetoslav Ganov54d068e2011-03-02 12:58:40 -08005952
5953 mSelf.mCoreSettingsObserver = new CoreSettingsObserver(mSelf);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005954 }
5955
Dianne Hackborncca1f0e2010-09-26 18:34:53 -07005956 /**
5957 * Allows app to retrieve the MIME type of a URI without having permission
5958 * to access its content provider.
5959 *
5960 * CTS tests for this functionality can be run with "runtest cts-appsecurity".
5961 *
5962 * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
5963 * src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
5964 */
5965 public String getProviderMimeType(Uri uri) {
5966 final String name = uri.getAuthority();
5967 final long ident = Binder.clearCallingIdentity();
5968 ContentProviderHolder holder = null;
5969
5970 try {
5971 holder = getContentProviderExternal(name);
5972 if (holder != null) {
5973 return holder.provider.getType(uri);
5974 }
5975 } catch (RemoteException e) {
5976 Log.w(TAG, "Content provider dead retrieving " + uri, e);
5977 return null;
5978 } finally {
5979 if (holder != null) {
5980 removeContentProviderExternal(name);
5981 }
5982 Binder.restoreCallingIdentity(ident);
5983 }
5984
5985 return null;
5986 }
5987
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005988 // =========================================================
5989 // GLOBAL MANAGEMENT
5990 // =========================================================
5991
5992 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
5993 ApplicationInfo info, String customProcess) {
5994 String proc = customProcess != null ? customProcess : info.processName;
5995 BatteryStatsImpl.Uid.Proc ps = null;
5996 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5997 synchronized (stats) {
5998 ps = stats.getProcessStatsLocked(info.uid, proc);
5999 }
6000 return new ProcessRecord(ps, thread, info, proc);
6001 }
6002
6003 final ProcessRecord addAppLocked(ApplicationInfo info) {
6004 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
6005
6006 if (app == null) {
6007 app = newProcessRecordLocked(null, info, null);
6008 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006009 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006010 }
6011
Dianne Hackborne7f97212011-02-24 14:40:20 -08006012 // This package really, really can not be stopped.
6013 try {
6014 AppGlobals.getPackageManager().setPackageStoppedState(
6015 info.packageName, false);
6016 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08006017 } catch (IllegalArgumentException e) {
6018 Slog.w(TAG, "Failed trying to unstop package "
6019 + info.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08006020 }
6021
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006022 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
6023 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
6024 app.persistent = true;
6025 app.maxAdj = CORE_SERVER_ADJ;
6026 }
6027 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
6028 mPersistentStartingProcesses.add(app);
6029 startProcessLocked(app, "added application", app.processName);
6030 }
6031
6032 return app;
6033 }
6034
6035 public void unhandledBack() {
6036 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
6037 "unhandledBack()");
6038
6039 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006040 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08006041 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006042 TAG, "Performing unhandledBack(): stack size = " + count);
6043 if (count > 1) {
6044 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006045 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006046 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
6047 Binder.restoreCallingIdentity(origId);
6048 }
6049 }
6050 }
6051
6052 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
6053 String name = uri.getAuthority();
6054 ContentProviderHolder cph = getContentProviderExternal(name);
6055 ParcelFileDescriptor pfd = null;
6056 if (cph != null) {
6057 // We record the binder invoker's uid in thread-local storage before
6058 // going to the content provider to open the file. Later, in the code
6059 // that handles all permissions checks, we look for this uid and use
6060 // that rather than the Activity Manager's own uid. The effect is that
6061 // we do the check against the caller's permissions even though it looks
6062 // to the content provider like the Activity Manager itself is making
6063 // the request.
6064 sCallerIdentity.set(new Identity(
6065 Binder.getCallingPid(), Binder.getCallingUid()));
6066 try {
6067 pfd = cph.provider.openFile(uri, "r");
6068 } catch (FileNotFoundException e) {
6069 // do nothing; pfd will be returned null
6070 } finally {
6071 // Ensure that whatever happens, we clean up the identity state
6072 sCallerIdentity.remove();
6073 }
6074
6075 // We've got the fd now, so we're done with the provider.
6076 removeContentProviderExternal(name);
6077 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006078 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006079 }
6080 return pfd;
6081 }
6082
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006083 // Actually is sleeping or shutting down or whatever else in the future
6084 // is an inactive state.
6085 public boolean isSleeping() {
6086 return mSleeping || mShuttingDown;
6087 }
6088
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006089 public void goingToSleep() {
6090 synchronized(this) {
6091 mSleeping = true;
6092 mWindowManager.setEventDispatching(false);
6093
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006094 mMainStack.stopIfSleepingLocked();
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07006095
6096 // Initialize the wake times of all processes.
Dianne Hackborn287952c2010-09-22 22:34:31 -07006097 checkExcessivePowerUsageLocked(false);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07006098 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
6099 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07006100 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006101 }
6102 }
6103
Dianne Hackborn55280a92009-05-07 15:53:46 -07006104 public boolean shutdown(int timeout) {
6105 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
6106 != PackageManager.PERMISSION_GRANTED) {
6107 throw new SecurityException("Requires permission "
6108 + android.Manifest.permission.SHUTDOWN);
6109 }
6110
6111 boolean timedout = false;
6112
6113 synchronized(this) {
6114 mShuttingDown = true;
6115 mWindowManager.setEventDispatching(false);
6116
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006117 if (mMainStack.mResumedActivity != null) {
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006118 mMainStack.stopIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07006119 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006120 while (mMainStack.mResumedActivity != null
6121 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07006122 long delay = endTime - System.currentTimeMillis();
6123 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006124 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07006125 timedout = true;
6126 break;
6127 }
6128 try {
6129 this.wait();
6130 } catch (InterruptedException e) {
6131 }
6132 }
6133 }
6134 }
6135
6136 mUsageStatsService.shutdown();
6137 mBatteryStatsService.shutdown();
6138
6139 return timedout;
6140 }
6141
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006142 public final void activitySlept(IBinder token) {
6143 if (localLOGV) Slog.v(
6144 TAG, "Activity slept: token=" + token);
6145
6146 ActivityRecord r = null;
6147
6148 final long origId = Binder.clearCallingIdentity();
6149
6150 synchronized (this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07006151 r = mMainStack.isInStackLocked(token);
6152 if (r != null) {
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006153 mMainStack.activitySleptLocked(r);
6154 }
6155 }
6156
6157 Binder.restoreCallingIdentity(origId);
6158 }
6159
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006160 public void wakingUp() {
6161 synchronized(this) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006162 mWindowManager.setEventDispatching(true);
6163 mSleeping = false;
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006164 mMainStack.awakeFromSleepingLocked();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006165 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006166 }
6167 }
6168
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006169 public void stopAppSwitches() {
6170 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
6171 != PackageManager.PERMISSION_GRANTED) {
6172 throw new SecurityException("Requires permission "
6173 + android.Manifest.permission.STOP_APP_SWITCHES);
6174 }
6175
6176 synchronized(this) {
6177 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
6178 + APP_SWITCH_DELAY_TIME;
6179 mDidAppSwitch = false;
6180 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
6181 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
6182 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
6183 }
6184 }
6185
6186 public void resumeAppSwitches() {
6187 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
6188 != PackageManager.PERMISSION_GRANTED) {
6189 throw new SecurityException("Requires permission "
6190 + android.Manifest.permission.STOP_APP_SWITCHES);
6191 }
6192
6193 synchronized(this) {
6194 // Note that we don't execute any pending app switches... we will
6195 // let those wait until either the timeout, or the next start
6196 // activity request.
6197 mAppSwitchesAllowedTime = 0;
6198 }
6199 }
6200
6201 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
6202 String name) {
6203 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
6204 return true;
6205 }
6206
6207 final int perm = checkComponentPermission(
6208 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08006209 callingUid, -1, true);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006210 if (perm == PackageManager.PERMISSION_GRANTED) {
6211 return true;
6212 }
6213
Joe Onorato8a9b2202010-02-26 18:56:32 -08006214 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006215 return false;
6216 }
6217
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006218 public void setDebugApp(String packageName, boolean waitForDebugger,
6219 boolean persistent) {
6220 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
6221 "setDebugApp()");
6222
6223 // Note that this is not really thread safe if there are multiple
6224 // callers into it at the same time, but that's not a situation we
6225 // care about.
6226 if (persistent) {
6227 final ContentResolver resolver = mContext.getContentResolver();
6228 Settings.System.putString(
6229 resolver, Settings.System.DEBUG_APP,
6230 packageName);
6231 Settings.System.putInt(
6232 resolver, Settings.System.WAIT_FOR_DEBUGGER,
6233 waitForDebugger ? 1 : 0);
6234 }
6235
6236 synchronized (this) {
6237 if (!persistent) {
6238 mOrigDebugApp = mDebugApp;
6239 mOrigWaitForDebugger = mWaitForDebugger;
6240 }
6241 mDebugApp = packageName;
6242 mWaitForDebugger = waitForDebugger;
6243 mDebugTransient = !persistent;
6244 if (packageName != null) {
6245 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006246 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006247 Binder.restoreCallingIdentity(origId);
6248 }
6249 }
6250 }
6251
6252 public void setAlwaysFinish(boolean enabled) {
6253 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
6254 "setAlwaysFinish()");
6255
6256 Settings.System.putInt(
6257 mContext.getContentResolver(),
6258 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
6259
6260 synchronized (this) {
6261 mAlwaysFinishActivities = enabled;
6262 }
6263 }
6264
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006265 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006266 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006267 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006268 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006269 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006270 }
6271 }
6272
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08006273 public boolean isUserAMonkey() {
6274 // For now the fact that there is a controller implies
6275 // we have a monkey.
6276 synchronized (this) {
6277 return mController != null;
6278 }
6279 }
6280
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006281 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06006282 synchronized (this) {
6283 mWatchers.register(watcher);
6284 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006285 }
6286
6287 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06006288 synchronized (this) {
6289 mWatchers.unregister(watcher);
6290 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006291 }
6292
Jeff Sharkeya4620792011-05-20 15:29:23 -07006293 public void registerProcessObserver(IProcessObserver observer) {
6294 mProcessObservers.register(observer);
6295 }
6296
6297 public void unregisterProcessObserver(IProcessObserver observer) {
6298 mProcessObservers.unregister(observer);
6299 }
6300
Daniel Sandler69a48172010-06-23 16:29:36 -04006301 public void setImmersive(IBinder token, boolean immersive) {
6302 synchronized(this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07006303 ActivityRecord r = mMainStack.isInStackLocked(token);
6304 if (r == null) {
Daniel Sandler69a48172010-06-23 16:29:36 -04006305 throw new IllegalArgumentException();
6306 }
Daniel Sandler69a48172010-06-23 16:29:36 -04006307 r.immersive = immersive;
6308 }
6309 }
6310
6311 public boolean isImmersive(IBinder token) {
6312 synchronized (this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07006313 ActivityRecord r = mMainStack.isInStackLocked(token);
6314 if (r == null) {
Daniel Sandler69a48172010-06-23 16:29:36 -04006315 throw new IllegalArgumentException();
6316 }
Daniel Sandler69a48172010-06-23 16:29:36 -04006317 return r.immersive;
6318 }
6319 }
6320
6321 public boolean isTopActivityImmersive() {
6322 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006323 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Daniel Sandler69a48172010-06-23 16:29:36 -04006324 return (r != null) ? r.immersive : false;
6325 }
6326 }
6327
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006328 public final void enterSafeMode() {
6329 synchronized(this) {
6330 // It only makes sense to do this before the system is ready
6331 // and started launching other packages.
6332 if (!mSystemReady) {
6333 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006334 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006335 } catch (RemoteException e) {
6336 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006337 }
6338 }
6339 }
6340
Jeff Brownb09abc12011-01-13 21:08:27 -08006341 public final void showSafeModeOverlay() {
6342 View v = LayoutInflater.from(mContext).inflate(
6343 com.android.internal.R.layout.safe_mode, null);
6344 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
6345 lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
6346 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
6347 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
6348 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
6349 lp.format = v.getBackground().getOpacity();
6350 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
6351 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
6352 ((WindowManager)mContext.getSystemService(
6353 Context.WINDOW_SERVICE)).addView(v, lp);
6354 }
6355
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006356 public void noteWakeupAlarm(IIntentSender sender) {
6357 if (!(sender instanceof PendingIntentRecord)) {
6358 return;
6359 }
6360 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
6361 synchronized (stats) {
6362 if (mBatteryStatsService.isOnBattery()) {
6363 mBatteryStatsService.enforceCallingPermission();
6364 PendingIntentRecord rec = (PendingIntentRecord)sender;
6365 int MY_UID = Binder.getCallingUid();
6366 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
6367 BatteryStatsImpl.Uid.Pkg pkg =
6368 stats.getPackageStatsLocked(uid, rec.key.packageName);
6369 pkg.incWakeupsLocked();
6370 }
6371 }
6372 }
6373
Dianne Hackborn64825172011-03-02 21:32:58 -08006374 public boolean killPids(int[] pids, String pReason, boolean secure) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006375 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006376 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006377 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006378 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006379 // XXX Note: don't acquire main activity lock here, because the window
6380 // manager calls in with its locks held.
6381
6382 boolean killed = false;
6383 synchronized (mPidsSelfLocked) {
6384 int[] types = new int[pids.length];
6385 int worstType = 0;
6386 for (int i=0; i<pids.length; i++) {
6387 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6388 if (proc != null) {
6389 int type = proc.setAdj;
6390 types[i] = type;
6391 if (type > worstType) {
6392 worstType = type;
6393 }
6394 }
6395 }
6396
Dianne Hackborn64825172011-03-02 21:32:58 -08006397 // If the worst oom_adj is somewhere in the hidden proc LRU range,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006398 // then constrain it so we will kill all hidden procs.
6399 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
6400 worstType = HIDDEN_APP_MIN_ADJ;
6401 }
Dianne Hackborn64825172011-03-02 21:32:58 -08006402
6403 // If this is not a secure call, don't let it kill processes that
6404 // are important.
6405 if (!secure && worstType < SECONDARY_SERVER_ADJ) {
6406 worstType = SECONDARY_SERVER_ADJ;
6407 }
6408
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006409 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006410 for (int i=0; i<pids.length; i++) {
6411 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6412 if (proc == null) {
6413 continue;
6414 }
6415 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006416 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07006417 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006418 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
6419 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006420 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006421 proc.killedBackground = true;
6422 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006423 }
6424 }
6425 }
6426 return killed;
6427 }
6428
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006429 public final void startRunning(String pkg, String cls, String action,
6430 String data) {
6431 synchronized(this) {
6432 if (mStartRunning) {
6433 return;
6434 }
6435 mStartRunning = true;
6436 mTopComponent = pkg != null && cls != null
6437 ? new ComponentName(pkg, cls) : null;
6438 mTopAction = action != null ? action : Intent.ACTION_MAIN;
6439 mTopData = data;
6440 if (!mSystemReady) {
6441 return;
6442 }
6443 }
6444
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006445 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006446 }
6447
6448 private void retrieveSettings() {
6449 final ContentResolver resolver = mContext.getContentResolver();
6450 String debugApp = Settings.System.getString(
6451 resolver, Settings.System.DEBUG_APP);
6452 boolean waitForDebugger = Settings.System.getInt(
6453 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
6454 boolean alwaysFinishActivities = Settings.System.getInt(
6455 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
6456
6457 Configuration configuration = new Configuration();
6458 Settings.System.getConfiguration(resolver, configuration);
6459
6460 synchronized (this) {
6461 mDebugApp = mOrigDebugApp = debugApp;
6462 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
6463 mAlwaysFinishActivities = alwaysFinishActivities;
6464 // This happens before any activities are started, so we can
6465 // change mConfiguration in-place.
6466 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08006467 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006468 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006469 }
6470 }
6471
6472 public boolean testIsSystemReady() {
6473 // no need to synchronize(this) just to read & return the value
6474 return mSystemReady;
6475 }
6476
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006477 private static File getCalledPreBootReceiversFile() {
6478 File dataDir = Environment.getDataDirectory();
6479 File systemDir = new File(dataDir, "system");
6480 File fname = new File(systemDir, "called_pre_boots.dat");
6481 return fname;
6482 }
6483
6484 private static ArrayList<ComponentName> readLastDonePreBootReceivers() {
6485 ArrayList<ComponentName> lastDoneReceivers = new ArrayList<ComponentName>();
6486 File file = getCalledPreBootReceiversFile();
6487 FileInputStream fis = null;
6488 try {
6489 fis = new FileInputStream(file);
6490 DataInputStream dis = new DataInputStream(new BufferedInputStream(fis, 2048));
6491 int vers = dis.readInt();
6492 String codename = dis.readUTF();
6493 if (vers == android.os.Build.VERSION.SDK_INT
6494 && codename.equals(android.os.Build.VERSION.CODENAME)) {
6495 int num = dis.readInt();
6496 while (num > 0) {
6497 num--;
6498 String pkg = dis.readUTF();
6499 String cls = dis.readUTF();
6500 lastDoneReceivers.add(new ComponentName(pkg, cls));
6501 }
6502 }
6503 } catch (FileNotFoundException e) {
6504 } catch (IOException e) {
6505 Slog.w(TAG, "Failure reading last done pre-boot receivers", e);
6506 } finally {
6507 if (fis != null) {
6508 try {
6509 fis.close();
6510 } catch (IOException e) {
6511 }
6512 }
6513 }
6514 return lastDoneReceivers;
6515 }
6516
6517 private static void writeLastDonePreBootReceivers(ArrayList<ComponentName> list) {
6518 File file = getCalledPreBootReceiversFile();
6519 FileOutputStream fos = null;
6520 DataOutputStream dos = null;
6521 try {
6522 Slog.i(TAG, "Writing new set of last done pre-boot receivers...");
6523 fos = new FileOutputStream(file);
6524 dos = new DataOutputStream(new BufferedOutputStream(fos, 2048));
6525 dos.writeInt(android.os.Build.VERSION.SDK_INT);
6526 dos.writeUTF(android.os.Build.VERSION.CODENAME);
6527 dos.writeInt(list.size());
6528 for (int i=0; i<list.size(); i++) {
6529 dos.writeUTF(list.get(i).getPackageName());
6530 dos.writeUTF(list.get(i).getClassName());
6531 }
6532 } catch (IOException e) {
6533 Slog.w(TAG, "Failure writing last done pre-boot receivers", e);
6534 file.delete();
6535 } finally {
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07006536 FileUtils.sync(fos);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006537 if (dos != null) {
6538 try {
6539 dos.close();
6540 } catch (IOException e) {
6541 // TODO Auto-generated catch block
6542 e.printStackTrace();
6543 }
6544 }
6545 }
6546 }
6547
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006548 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006549 synchronized(this) {
6550 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006551 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006552 return;
6553 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006554
6555 // Check to see if there are any update receivers to run.
6556 if (!mDidUpdate) {
6557 if (mWaitingUpdate) {
6558 return;
6559 }
6560 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
6561 List<ResolveInfo> ris = null;
6562 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006563 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006564 intent, null, 0);
6565 } catch (RemoteException e) {
6566 }
6567 if (ris != null) {
6568 for (int i=ris.size()-1; i>=0; i--) {
6569 if ((ris.get(i).activityInfo.applicationInfo.flags
6570 &ApplicationInfo.FLAG_SYSTEM) == 0) {
6571 ris.remove(i);
6572 }
6573 }
6574 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006575
6576 ArrayList<ComponentName> lastDoneReceivers = readLastDonePreBootReceivers();
6577
6578 final ArrayList<ComponentName> doneReceivers = new ArrayList<ComponentName>();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006579 for (int i=0; i<ris.size(); i++) {
6580 ActivityInfo ai = ris.get(i).activityInfo;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006581 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6582 if (lastDoneReceivers.contains(comp)) {
6583 ris.remove(i);
6584 i--;
6585 }
6586 }
6587
6588 for (int i=0; i<ris.size(); i++) {
6589 ActivityInfo ai = ris.get(i).activityInfo;
6590 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6591 doneReceivers.add(comp);
6592 intent.setComponent(comp);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006593 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08006594 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006595 finisher = new IIntentReceiver.Stub() {
6596 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07006597 String data, Bundle extras, boolean ordered,
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006598 boolean sticky) {
6599 // The raw IIntentReceiver interface is called
6600 // with the AM lock held, so redispatch to
6601 // execute our code without the lock.
6602 mHandler.post(new Runnable() {
6603 public void run() {
6604 synchronized (ActivityManagerService.this) {
6605 mDidUpdate = true;
6606 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006607 writeLastDonePreBootReceivers(doneReceivers);
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006608 systemReady(goingCallback);
6609 }
6610 });
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006611 }
6612 };
6613 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006614 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006615 broadcastIntentLocked(null, null, intent, null, finisher,
6616 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08006617 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006618 mWaitingUpdate = true;
6619 }
6620 }
6621 }
6622 if (mWaitingUpdate) {
6623 return;
6624 }
6625 mDidUpdate = true;
6626 }
6627
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006628 mSystemReady = true;
6629 if (!mStartRunning) {
6630 return;
6631 }
6632 }
6633
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006634 ArrayList<ProcessRecord> procsToKill = null;
6635 synchronized(mPidsSelfLocked) {
6636 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
6637 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
6638 if (!isAllowedWhileBooting(proc.info)){
6639 if (procsToKill == null) {
6640 procsToKill = new ArrayList<ProcessRecord>();
6641 }
6642 procsToKill.add(proc);
6643 }
6644 }
6645 }
6646
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006647 synchronized(this) {
6648 if (procsToKill != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006649 for (int i=procsToKill.size()-1; i>=0; i--) {
6650 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08006651 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006652 removeProcessLocked(proc, true);
6653 }
6654 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006655
6656 // Now that we have cleaned up any update processes, we
6657 // are ready to start launching real processes and know that
6658 // we won't trample on them any more.
6659 mProcessesReady = true;
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006660 }
6661
Joe Onorato8a9b2202010-02-26 18:56:32 -08006662 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006663 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006664 SystemClock.uptimeMillis());
6665
6666 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006667 // Make sure we have no pre-ready processes sitting around.
6668
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006669 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
6670 ResolveInfo ri = mContext.getPackageManager()
6671 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07006672 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006673 CharSequence errorMsg = null;
6674 if (ri != null) {
6675 ActivityInfo ai = ri.activityInfo;
6676 ApplicationInfo app = ai.applicationInfo;
6677 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
6678 mTopAction = Intent.ACTION_FACTORY_TEST;
6679 mTopData = null;
6680 mTopComponent = new ComponentName(app.packageName,
6681 ai.name);
6682 } else {
6683 errorMsg = mContext.getResources().getText(
6684 com.android.internal.R.string.factorytest_not_system);
6685 }
6686 } else {
6687 errorMsg = mContext.getResources().getText(
6688 com.android.internal.R.string.factorytest_no_action);
6689 }
6690 if (errorMsg != null) {
6691 mTopAction = null;
6692 mTopData = null;
6693 mTopComponent = null;
6694 Message msg = Message.obtain();
6695 msg.what = SHOW_FACTORY_ERROR_MSG;
6696 msg.getData().putCharSequence("msg", errorMsg);
6697 mHandler.sendMessage(msg);
6698 }
6699 }
6700 }
6701
6702 retrieveSettings();
6703
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006704 if (goingCallback != null) goingCallback.run();
6705
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006706 synchronized (this) {
6707 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
6708 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006709 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07006710 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006711 if (apps != null) {
6712 int N = apps.size();
6713 int i;
6714 for (i=0; i<N; i++) {
6715 ApplicationInfo info
6716 = (ApplicationInfo)apps.get(i);
6717 if (info != null &&
6718 !info.packageName.equals("android")) {
6719 addAppLocked(info);
6720 }
6721 }
6722 }
6723 } catch (RemoteException ex) {
6724 // pm is in same process, this will never happen.
6725 }
6726 }
6727
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006728 // Start up initial activity.
6729 mBooting = true;
6730
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006731 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006732 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006733 Message msg = Message.obtain();
6734 msg.what = SHOW_UID_ERROR_MSG;
6735 mHandler.sendMessage(msg);
6736 }
6737 } catch (RemoteException e) {
6738 }
6739
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006740 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006741 }
6742 }
6743
Dan Egnorb7f03672009-12-09 16:22:32 -08006744 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006745 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006746 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006747 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006748 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006749 startAppProblemLocked(app);
6750 app.stopFreezingAllLocked();
6751 return handleAppCrashLocked(app);
6752 }
6753
Dan Egnorb7f03672009-12-09 16:22:32 -08006754 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006755 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006756 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006757 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006758 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
6759 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006760 startAppProblemLocked(app);
6761 app.stopFreezingAllLocked();
6762 }
6763
6764 /**
6765 * Generate a process error record, suitable for attachment to a ProcessRecord.
6766 *
6767 * @param app The ProcessRecord in which the error occurred.
6768 * @param condition Crashing, Application Not Responding, etc. Values are defined in
6769 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08006770 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006771 * @param shortMsg Short message describing the crash.
6772 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08006773 * @param stackTrace Full crash stack trace, may be null.
6774 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006775 * @return Returns a fully-formed AppErrorStateInfo record.
6776 */
6777 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006778 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006779 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08006780
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006781 report.condition = condition;
6782 report.processName = app.processName;
6783 report.pid = app.pid;
6784 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08006785 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006786 report.shortMsg = shortMsg;
6787 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08006788 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006789
6790 return report;
6791 }
6792
Dan Egnor42471dd2010-01-07 17:25:22 -08006793 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006794 synchronized (this) {
6795 app.crashing = false;
6796 app.crashingReport = null;
6797 app.notResponding = false;
6798 app.notRespondingReport = null;
6799 if (app.anrDialog == fromDialog) {
6800 app.anrDialog = null;
6801 }
6802 if (app.waitDialog == fromDialog) {
6803 app.waitDialog = null;
6804 }
6805 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08006806 handleAppCrashLocked(app);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07006807 Slog.i(ActivityManagerService.TAG, "Killing " + app + ": user's request");
Dianne Hackborn8633e682010-04-22 16:03:41 -07006808 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
6809 app.processName, app.setAdj, "user's request after error");
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07006810 Process.killProcessQuiet(app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006811 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006812 }
6813 }
Dan Egnor42471dd2010-01-07 17:25:22 -08006814
Dan Egnorb7f03672009-12-09 16:22:32 -08006815 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006816 long now = SystemClock.uptimeMillis();
6817
6818 Long crashTime = mProcessCrashTimes.get(app.info.processName,
6819 app.info.uid);
6820 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
6821 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006822 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006823 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006824 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006825 app.info.processName, app.info.uid);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006826 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
6827 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006828 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006829 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006830 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006831 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006832 }
6833 }
6834 if (!app.persistent) {
Dianne Hackborn070783f2010-12-29 16:46:28 -08006835 // Don't let services in this process be restarted and potentially
6836 // annoy the user repeatedly. Unless it is persistent, since those
6837 // processes run critical code.
6838 killServicesLocked(app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006839 // We don't want to start this process again until the user
6840 // explicitly does so... but for persistent process, we really
6841 // need to keep it running. If a persistent process is actually
6842 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08006843 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006844 app.info.processName);
6845 mBadProcesses.put(app.info.processName, app.info.uid, now);
6846 app.bad = true;
6847 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
6848 app.removed = true;
6849 removeProcessLocked(app, false);
Dianne Hackborncb44d962011-03-10 17:02:27 -08006850 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006851 return false;
6852 }
Dianne Hackborncb44d962011-03-10 17:02:27 -08006853 mMainStack.resumeTopActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006854 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006855 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006856 if (r.app == app) {
6857 // If the top running activity is from this crashing
6858 // process, then terminate it to avoid getting in a loop.
6859 Slog.w(TAG, " Force finishing activity "
6860 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006861 int index = mMainStack.indexOfTokenLocked(r);
6862 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006863 Activity.RESULT_CANCELED, null, "crashed");
Dianne Hackborn070783f2010-12-29 16:46:28 -08006864 // Also terminate any activities below it that aren't yet
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006865 // stopped, to avoid a situation where one will get
6866 // re-start our crashing activity once it gets resumed again.
6867 index--;
6868 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006869 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006870 if (r.state == ActivityState.RESUMED
6871 || r.state == ActivityState.PAUSING
6872 || r.state == ActivityState.PAUSED) {
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -08006873 if (!r.isHomeActivity || mHomeProcess != r.app) {
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006874 Slog.w(TAG, " Force finishing activity "
6875 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006876 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006877 Activity.RESULT_CANCELED, null, "crashed");
6878 }
6879 }
6880 }
6881 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006882 }
6883
6884 // Bump up the crash count of any services currently running in the proc.
6885 if (app.services.size() != 0) {
6886 // Any services running in the application need to be placed
6887 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07006888 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006889 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006890 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006891 sr.crashCount++;
6892 }
6893 }
Mattias Larssona4fd0072010-06-22 22:37:03 +02006894
6895 // If the crashing process is what we consider to be the "home process" and it has been
6896 // replaced by a third-party app, clear the package preferred activities from packages
6897 // with a home activity running in the process to prevent a repeatedly crashing app
6898 // from blocking the user to manually clear the list.
6899 if (app == mHomeProcess && mHomeProcess.activities.size() > 0
6900 && (mHomeProcess.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
6901 Iterator it = mHomeProcess.activities.iterator();
6902 while (it.hasNext()) {
Jean-Baptiste Queru5ea89f72010-07-30 09:30:31 -07006903 ActivityRecord r = (ActivityRecord)it.next();
Mattias Larssona4fd0072010-06-22 22:37:03 +02006904 if (r.isHomeActivity) {
6905 Log.i(TAG, "Clearing package preferred activities from " + r.packageName);
6906 try {
6907 ActivityThread.getPackageManager()
6908 .clearPackagePreferredActivities(r.packageName);
6909 } catch (RemoteException c) {
6910 // pm is in same process, this will never happen.
6911 }
6912 }
6913 }
6914 }
6915
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006916 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
6917 return true;
6918 }
6919
6920 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006921 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
6922 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006923 skipCurrentReceiverLocked(app);
6924 }
6925
6926 void skipCurrentReceiverLocked(ProcessRecord app) {
6927 boolean reschedule = false;
6928 BroadcastRecord r = app.curReceiver;
6929 if (r != null) {
6930 // The current broadcast is waiting for this app's receiver
6931 // to be finished. Looks like that's not going to happen, so
6932 // let the broadcast continue.
Jeff Brown4d94a762010-09-23 11:33:28 -07006933 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006934 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6935 r.resultExtras, r.resultAbort, true);
6936 reschedule = true;
6937 }
6938 r = mPendingBroadcast;
6939 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006940 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006941 "skip & discard pending app " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -07006942 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006943 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6944 r.resultExtras, r.resultAbort, true);
6945 reschedule = true;
6946 }
6947 if (reschedule) {
6948 scheduleBroadcastsLocked();
6949 }
6950 }
6951
Dan Egnor60d87622009-12-16 16:32:58 -08006952 /**
6953 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
6954 * The application process will exit immediately after this call returns.
6955 * @param app object of the crashing app, null for the system server
6956 * @param crashInfo describing the exception
6957 */
6958 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
Dianne Hackborncb44d962011-03-10 17:02:27 -08006959 ProcessRecord r = findAppProcess(app, "Crash");
Dan Egnor60d87622009-12-16 16:32:58 -08006960
6961 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
6962 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006963 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006964 crashInfo.exceptionClassName,
6965 crashInfo.exceptionMessage,
6966 crashInfo.throwFileName,
6967 crashInfo.throwLineNumber);
6968
Dan Egnor42471dd2010-01-07 17:25:22 -08006969 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006970
6971 crashApplication(r, crashInfo);
6972 }
6973
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006974 public void handleApplicationStrictModeViolation(
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006975 IBinder app,
6976 int violationMask,
6977 StrictMode.ViolationInfo info) {
Dianne Hackborncb44d962011-03-10 17:02:27 -08006978 ProcessRecord r = findAppProcess(app, "StrictMode");
6979 if (r == null) {
6980 return;
6981 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006982
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006983 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -08006984 Integer stackFingerprint = info.hashCode();
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006985 boolean logIt = true;
6986 synchronized (mAlreadyLoggedViolatedStacks) {
6987 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
6988 logIt = false;
6989 // TODO: sub-sample into EventLog for these, with
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006990 // the info.durationMillis? Then we'd get
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006991 // the relative pain numbers, without logging all
6992 // the stack traces repeatedly. We'd want to do
6993 // likewise in the client code, which also does
6994 // dup suppression, before the Binder call.
6995 } else {
6996 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
6997 mAlreadyLoggedViolatedStacks.clear();
6998 }
6999 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
7000 }
7001 }
7002 if (logIt) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007003 logStrictModeViolationToDropBox(r, info);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07007004 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07007005 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07007006
7007 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
7008 AppErrorResult result = new AppErrorResult();
7009 synchronized (this) {
7010 final long origId = Binder.clearCallingIdentity();
7011
7012 Message msg = Message.obtain();
7013 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
7014 HashMap<String, Object> data = new HashMap<String, Object>();
7015 data.put("result", result);
7016 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07007017 data.put("violationMask", violationMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007018 data.put("info", info);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07007019 msg.obj = data;
7020 mHandler.sendMessage(msg);
7021
7022 Binder.restoreCallingIdentity(origId);
7023 }
7024 int res = result.get();
Dianne Hackbornb424b632010-08-18 15:59:05 -07007025 Slog.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07007026 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07007027 }
7028
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007029 // Depending on the policy in effect, there could be a bunch of
7030 // these in quick succession so we try to batch these together to
7031 // minimize disk writes, number of dropbox entries, and maximize
7032 // compression, by having more fewer, larger records.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007033 private void logStrictModeViolationToDropBox(
7034 ProcessRecord process,
7035 StrictMode.ViolationInfo info) {
7036 if (info == null) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007037 return;
7038 }
7039 final boolean isSystemApp = process == null ||
7040 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
7041 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
7042 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
7043 final DropBoxManager dbox = (DropBoxManager)
7044 mContext.getSystemService(Context.DROPBOX_SERVICE);
7045
7046 // Exit early if the dropbox isn't configured to accept this report type.
7047 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
7048
7049 boolean bufferWasEmpty;
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007050 boolean needsFlush;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007051 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
7052 synchronized (sb) {
7053 bufferWasEmpty = sb.length() == 0;
7054 appendDropBoxProcessHeaders(process, sb);
7055 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
7056 sb.append("System-App: ").append(isSystemApp).append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007057 sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
7058 if (info.violationNumThisLoop != 0) {
7059 sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
7060 }
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07007061 if (info.numAnimationsRunning != 0) {
7062 sb.append("Animations-Running: ").append(info.numAnimationsRunning).append("\n");
7063 }
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07007064 if (info.broadcastIntentAction != null) {
7065 sb.append("Broadcast-Intent-Action: ").append(info.broadcastIntentAction).append("\n");
7066 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08007067 if (info.durationMillis != -1) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007068 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007069 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08007070 if (info.numInstances != -1) {
7071 sb.append("Instance-Count: ").append(info.numInstances).append("\n");
7072 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08007073 if (info.tags != null) {
7074 for (String tag : info.tags) {
7075 sb.append("Span-Tag: ").append(tag).append("\n");
7076 }
7077 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007078 sb.append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007079 if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
7080 sb.append(info.crashInfo.stackTrace);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007081 }
7082 sb.append("\n");
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007083
7084 // Only buffer up to ~64k. Various logging bits truncate
7085 // things at 128k.
7086 needsFlush = (sb.length() > 64 * 1024);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007087 }
7088
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007089 // Flush immediately if the buffer's grown too large, or this
7090 // is a non-system app. Non-system apps are isolated with a
7091 // different tag & policy and not batched.
7092 //
7093 // Batching is useful during internal testing with
7094 // StrictMode settings turned up high. Without batching,
7095 // thousands of separate files could be created on boot.
7096 if (!isSystemApp || needsFlush) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007097 new Thread("Error dump: " + dropboxTag) {
7098 @Override
7099 public void run() {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007100 String report;
7101 synchronized (sb) {
7102 report = sb.toString();
7103 sb.delete(0, sb.length());
7104 sb.trimToSize();
7105 }
7106 if (report.length() != 0) {
7107 dbox.addText(dropboxTag, report);
7108 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007109 }
7110 }.start();
7111 return;
7112 }
7113
7114 // System app batching:
7115 if (!bufferWasEmpty) {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007116 // An existing dropbox-writing thread is outstanding, so
7117 // we don't need to start it up. The existing thread will
7118 // catch the buffer appends we just did.
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007119 return;
7120 }
7121
7122 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
7123 // (After this point, we shouldn't access AMS internal data structures.)
7124 new Thread("Error dump: " + dropboxTag) {
7125 @Override
7126 public void run() {
7127 // 5 second sleep to let stacks arrive and be batched together
7128 try {
7129 Thread.sleep(5000); // 5 seconds
7130 } catch (InterruptedException e) {}
7131
7132 String errorReport;
7133 synchronized (mStrictModeBuffer) {
7134 errorReport = mStrictModeBuffer.toString();
7135 if (errorReport.length() == 0) {
7136 return;
7137 }
7138 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
7139 mStrictModeBuffer.trimToSize();
7140 }
7141 dbox.addText(dropboxTag, errorReport);
7142 }
7143 }.start();
7144 }
7145
Dan Egnor60d87622009-12-16 16:32:58 -08007146 /**
7147 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
7148 * @param app object of the crashing app, null for the system server
7149 * @param tag reported by the caller
7150 * @param crashInfo describing the context of the error
7151 * @return true if the process should exit immediately (WTF is fatal)
7152 */
7153 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08007154 ApplicationErrorReport.CrashInfo crashInfo) {
Dianne Hackborncb44d962011-03-10 17:02:27 -08007155 ProcessRecord r = findAppProcess(app, "WTF");
Dan Egnor60d87622009-12-16 16:32:58 -08007156
7157 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
7158 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08007159 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08007160 tag, crashInfo.exceptionMessage);
7161
Dan Egnor42471dd2010-01-07 17:25:22 -08007162 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08007163
Dianne Hackborn1ab43772011-03-15 14:38:02 -07007164 if (r != null && r.pid != Process.myPid() &&
7165 Settings.Secure.getInt(mContext.getContentResolver(),
7166 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08007167 crashApplication(r, crashInfo);
7168 return true;
7169 } else {
7170 return false;
7171 }
7172 }
7173
7174 /**
7175 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
7176 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
7177 */
Dianne Hackborncb44d962011-03-10 17:02:27 -08007178 private ProcessRecord findAppProcess(IBinder app, String reason) {
Dan Egnor60d87622009-12-16 16:32:58 -08007179 if (app == null) {
7180 return null;
7181 }
7182
7183 synchronized (this) {
7184 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
7185 final int NA = apps.size();
7186 for (int ia=0; ia<NA; ia++) {
7187 ProcessRecord p = apps.valueAt(ia);
7188 if (p.thread != null && p.thread.asBinder() == app) {
7189 return p;
7190 }
7191 }
7192 }
7193
Dianne Hackborncb44d962011-03-10 17:02:27 -08007194 Slog.w(TAG, "Can't find mystery application for " + reason
7195 + " from pid=" + Binder.getCallingPid()
7196 + " uid=" + Binder.getCallingUid() + ": " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08007197 return null;
7198 }
7199 }
7200
7201 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007202 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
7203 * to append various headers to the dropbox log text.
Dan Egnor60d87622009-12-16 16:32:58 -08007204 */
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07007205 private void appendDropBoxProcessHeaders(ProcessRecord process, StringBuilder sb) {
Vairavan Srinivasan68a4e0a2011-02-14 20:45:59 -08007206 // Watchdog thread ends up invoking this function (with
7207 // a null ProcessRecord) to add the stack file to dropbox.
7208 // Do not acquire a lock on this (am) in such cases, as it
7209 // could cause a potential deadlock, if and when watchdog
7210 // is invoked due to unavailability of lock on am and it
7211 // would prevent watchdog from killing system_server.
7212 if (process == null) {
7213 sb.append("Process: system_server\n");
7214 return;
7215 }
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07007216 // Note: ProcessRecord 'process' is guarded by the service
7217 // instance. (notably process.pkgList, which could otherwise change
7218 // concurrently during execution of this method)
7219 synchronized (this) {
Vairavan Srinivasan68a4e0a2011-02-14 20:45:59 -08007220 if (process.pid == MY_PID) {
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07007221 sb.append("Process: system_server\n");
7222 } else {
7223 sb.append("Process: ").append(process.processName).append("\n");
7224 }
Dan Egnora455d192010-03-12 08:52:28 -08007225 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007226 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08007227 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
7228 for (String pkg : process.pkgList) {
7229 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08007230 try {
Dan Egnora455d192010-03-12 08:52:28 -08007231 PackageInfo pi = pm.getPackageInfo(pkg, 0);
7232 if (pi != null) {
7233 sb.append(" v").append(pi.versionCode);
7234 if (pi.versionName != null) {
7235 sb.append(" (").append(pi.versionName).append(")");
7236 }
7237 }
7238 } catch (RemoteException e) {
7239 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08007240 }
Dan Egnora455d192010-03-12 08:52:28 -08007241 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08007242 }
Dan Egnora455d192010-03-12 08:52:28 -08007243 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007244 }
7245
7246 private static String processClass(ProcessRecord process) {
7247 if (process == null || process.pid == MY_PID) {
7248 return "system_server";
7249 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
7250 return "system_app";
7251 } else {
7252 return "data_app";
7253 }
7254 }
7255
7256 /**
7257 * Write a description of an error (crash, WTF, ANR) to the drop box.
7258 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
7259 * @param process which caused the error, null means the system server
7260 * @param activity which triggered the error, null if unknown
7261 * @param parent activity related to the error, null if unknown
7262 * @param subject line related to the error, null if absent
7263 * @param report in long form describing the error, null if absent
7264 * @param logFile to include in the report, null if none
7265 * @param crashInfo giving an application stack trace, null if absent
7266 */
7267 public void addErrorToDropBox(String eventType,
7268 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
7269 final String report, final File logFile,
7270 final ApplicationErrorReport.CrashInfo crashInfo) {
7271 // NOTE -- this must never acquire the ActivityManagerService lock,
7272 // otherwise the watchdog may be prevented from resetting the system.
7273
7274 final String dropboxTag = processClass(process) + "_" + eventType;
7275 final DropBoxManager dbox = (DropBoxManager)
7276 mContext.getSystemService(Context.DROPBOX_SERVICE);
7277
7278 // Exit early if the dropbox isn't configured to accept this report type.
7279 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
7280
7281 final StringBuilder sb = new StringBuilder(1024);
7282 appendDropBoxProcessHeaders(process, sb);
Dan Egnora455d192010-03-12 08:52:28 -08007283 if (activity != null) {
7284 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
7285 }
7286 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
7287 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
7288 }
7289 if (parent != null && parent != activity) {
7290 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
7291 }
7292 if (subject != null) {
7293 sb.append("Subject: ").append(subject).append("\n");
7294 }
7295 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
Christian Lindeberg03d2ca62010-09-28 14:52:20 +02007296 if (Debug.isDebuggerConnected()) {
7297 sb.append("Debugger: Connected\n");
7298 }
Dan Egnora455d192010-03-12 08:52:28 -08007299 sb.append("\n");
7300
7301 // Do the rest in a worker thread to avoid blocking the caller on I/O
7302 // (After this point, we shouldn't access AMS internal data structures.)
7303 Thread worker = new Thread("Error dump: " + dropboxTag) {
7304 @Override
7305 public void run() {
7306 if (report != null) {
7307 sb.append(report);
7308 }
7309 if (logFile != null) {
7310 try {
7311 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
7312 } catch (IOException e) {
7313 Slog.e(TAG, "Error reading " + logFile, e);
7314 }
7315 }
7316 if (crashInfo != null && crashInfo.stackTrace != null) {
7317 sb.append(crashInfo.stackTrace);
7318 }
7319
7320 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
7321 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
7322 if (lines > 0) {
7323 sb.append("\n");
7324
7325 // Merge several logcat streams, and take the last N lines
7326 InputStreamReader input = null;
7327 try {
7328 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
7329 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
7330 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
7331
7332 try { logcat.getOutputStream().close(); } catch (IOException e) {}
7333 try { logcat.getErrorStream().close(); } catch (IOException e) {}
7334 input = new InputStreamReader(logcat.getInputStream());
7335
7336 int num;
7337 char[] buf = new char[8192];
7338 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
7339 } catch (IOException e) {
7340 Slog.e(TAG, "Error running logcat", e);
7341 } finally {
7342 if (input != null) try { input.close(); } catch (IOException e) {}
7343 }
7344 }
7345
7346 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08007347 }
Dan Egnora455d192010-03-12 08:52:28 -08007348 };
7349
7350 if (process == null || process.pid == MY_PID) {
7351 worker.run(); // We may be about to die -- need to run this synchronously
7352 } else {
7353 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08007354 }
7355 }
7356
7357 /**
7358 * Bring up the "unexpected error" dialog box for a crashing app.
7359 * Deal with edge cases (intercepts from instrumented applications,
7360 * ActivityController, error intent receivers, that sort of thing).
7361 * @param r the application crashing
7362 * @param crashInfo describing the failure
7363 */
7364 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007365 long timeMillis = System.currentTimeMillis();
7366 String shortMsg = crashInfo.exceptionClassName;
7367 String longMsg = crashInfo.exceptionMessage;
7368 String stackTrace = crashInfo.stackTrace;
7369 if (shortMsg != null && longMsg != null) {
7370 longMsg = shortMsg + ": " + longMsg;
7371 } else if (shortMsg != null) {
7372 longMsg = shortMsg;
7373 }
7374
Dan Egnor60d87622009-12-16 16:32:58 -08007375 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007376 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007377 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007378 try {
7379 String name = r != null ? r.processName : null;
7380 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08007381 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08007382 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007383 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007384 + " at watcher's request");
7385 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08007386 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007387 }
7388 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007389 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007390 }
7391 }
7392
7393 final long origId = Binder.clearCallingIdentity();
7394
7395 // If this process is running instrumentation, finish it.
7396 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007397 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007398 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08007399 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
7400 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007401 Bundle info = new Bundle();
7402 info.putString("shortMsg", shortMsg);
7403 info.putString("longMsg", longMsg);
7404 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
7405 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007406 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007407 }
7408
Dan Egnor60d87622009-12-16 16:32:58 -08007409 // If we can't identify the process or it's already exceeded its crash quota,
7410 // quit right away without showing a crash dialog.
7411 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007412 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007413 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007414 }
7415
7416 Message msg = Message.obtain();
7417 msg.what = SHOW_ERROR_MSG;
7418 HashMap data = new HashMap();
7419 data.put("result", result);
7420 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007421 msg.obj = data;
7422 mHandler.sendMessage(msg);
7423
7424 Binder.restoreCallingIdentity(origId);
7425 }
7426
7427 int res = result.get();
7428
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007429 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007430 synchronized (this) {
7431 if (r != null) {
7432 mProcessCrashTimes.put(r.info.processName, r.info.uid,
7433 SystemClock.uptimeMillis());
7434 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007435 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007436 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007437 }
7438 }
7439
7440 if (appErrorIntent != null) {
7441 try {
7442 mContext.startActivity(appErrorIntent);
7443 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007444 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007445 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007446 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007447 }
Dan Egnorb7f03672009-12-09 16:22:32 -08007448
7449 Intent createAppErrorIntentLocked(ProcessRecord r,
7450 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
7451 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007452 if (report == null) {
7453 return null;
7454 }
7455 Intent result = new Intent(Intent.ACTION_APP_ERROR);
7456 result.setComponent(r.errorReportReceiver);
7457 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
7458 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
7459 return result;
7460 }
7461
Dan Egnorb7f03672009-12-09 16:22:32 -08007462 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
7463 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007464 if (r.errorReportReceiver == null) {
7465 return null;
7466 }
7467
7468 if (!r.crashing && !r.notResponding) {
7469 return null;
7470 }
7471
Dan Egnorb7f03672009-12-09 16:22:32 -08007472 ApplicationErrorReport report = new ApplicationErrorReport();
7473 report.packageName = r.info.packageName;
7474 report.installerPackageName = r.errorReportReceiver.getPackageName();
7475 report.processName = r.processName;
7476 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01007477 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007478
Dan Egnorb7f03672009-12-09 16:22:32 -08007479 if (r.crashing) {
7480 report.type = ApplicationErrorReport.TYPE_CRASH;
7481 report.crashInfo = crashInfo;
7482 } else if (r.notResponding) {
7483 report.type = ApplicationErrorReport.TYPE_ANR;
7484 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007485
Dan Egnorb7f03672009-12-09 16:22:32 -08007486 report.anrInfo.activity = r.notRespondingReport.tag;
7487 report.anrInfo.cause = r.notRespondingReport.shortMsg;
7488 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007489 }
7490
Dan Egnorb7f03672009-12-09 16:22:32 -08007491 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007492 }
7493
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007494 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
7495 // assume our apps are happy - lazy create the list
7496 List<ActivityManager.ProcessErrorStateInfo> errList = null;
7497
7498 synchronized (this) {
7499
7500 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007501 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7502 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007503 if ((app.thread != null) && (app.crashing || app.notResponding)) {
7504 // This one's in trouble, so we'll generate a report for it
7505 // crashes are higher priority (in case there's a crash *and* an anr)
7506 ActivityManager.ProcessErrorStateInfo report = null;
7507 if (app.crashing) {
7508 report = app.crashingReport;
7509 } else if (app.notResponding) {
7510 report = app.notRespondingReport;
7511 }
7512
7513 if (report != null) {
7514 if (errList == null) {
7515 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
7516 }
7517 errList.add(report);
7518 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007519 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007520 " crashing = " + app.crashing +
7521 " notResponding = " + app.notResponding);
7522 }
7523 }
7524 }
7525 }
7526
7527 return errList;
7528 }
7529
7530 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
7531 // Lazy instantiation of list
7532 List<ActivityManager.RunningAppProcessInfo> runList = null;
7533 synchronized (this) {
7534 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007535 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7536 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007537 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
7538 // Generate process state info for running application
7539 ActivityManager.RunningAppProcessInfo currApp =
7540 new ActivityManager.RunningAppProcessInfo(app.processName,
7541 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07007542 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007543 if (mHeavyWeightProcess == app) {
Dianne Hackborn482566e2010-09-03 12:51:28 -07007544 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007545 }
Dianne Hackborn42499172010-10-15 18:45:07 -07007546 if (app.persistent) {
7547 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_PERSISTENT;
7548 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007549 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007550 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007551 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
7552 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
7553 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08007554 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
7555 } else if (adj >= HOME_APP_ADJ) {
7556 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
7557 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007558 } else if (adj >= SECONDARY_SERVER_ADJ) {
7559 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007560 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackborn5383f502010-10-22 12:59:20 -07007561 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007562 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
7563 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007564 } else if (adj >= VISIBLE_APP_ADJ) {
7565 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
7566 } else {
7567 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
7568 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007569 currApp.importanceReasonCode = app.adjTypeCode;
7570 if (app.adjSource instanceof ProcessRecord) {
7571 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007572 } else if (app.adjSource instanceof ActivityRecord) {
7573 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007574 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
7575 }
7576 if (app.adjTarget instanceof ComponentName) {
7577 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
7578 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007579 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007580 // + " lru=" + currApp.lru);
7581 if (runList == null) {
7582 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
7583 }
7584 runList.add(currApp);
7585 }
7586 }
7587 }
7588 return runList;
7589 }
7590
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007591 public List<ApplicationInfo> getRunningExternalApplications() {
7592 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
7593 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
7594 if (runningApps != null && runningApps.size() > 0) {
7595 Set<String> extList = new HashSet<String>();
7596 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
7597 if (app.pkgList != null) {
7598 for (String pkg : app.pkgList) {
7599 extList.add(pkg);
7600 }
7601 }
7602 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007603 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007604 for (String pkg : extList) {
7605 try {
7606 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
7607 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
7608 retList.add(info);
7609 }
7610 } catch (RemoteException e) {
7611 }
7612 }
7613 }
7614 return retList;
7615 }
7616
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007617 @Override
7618 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007619 if (checkCallingPermission(android.Manifest.permission.DUMP)
7620 != PackageManager.PERMISSION_GRANTED) {
7621 pw.println("Permission Denial: can't dump ActivityManager from from pid="
7622 + Binder.getCallingPid()
7623 + ", uid=" + Binder.getCallingUid()
7624 + " without permission "
7625 + android.Manifest.permission.DUMP);
7626 return;
7627 }
7628
7629 boolean dumpAll = false;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007630 boolean dumpClient = false;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007631
7632 int opti = 0;
7633 while (opti < args.length) {
7634 String opt = args[opti];
7635 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
7636 break;
7637 }
7638 opti++;
7639 if ("-a".equals(opt)) {
7640 dumpAll = true;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007641 } else if ("-c".equals(opt)) {
7642 dumpClient = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007643 } else if ("-h".equals(opt)) {
7644 pw.println("Activity manager dump options:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007645 pw.println(" [-a] [-c] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007646 pw.println(" cmd may be one of:");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007647 pw.println(" a[ctivities]: activity stack state");
7648 pw.println(" b[roadcasts]: broadcast state");
7649 pw.println(" i[ntents]: pending intent state");
7650 pw.println(" p[rocesses]: process state");
7651 pw.println(" o[om]: out of memory management");
7652 pw.println(" prov[iders]: content provider state");
7653 pw.println(" s[ervices]: service state");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007654 pw.println(" service [COMP_SPEC]: service client-side state");
7655 pw.println(" cmd may also be a COMP_SPEC to dump activities.");
7656 pw.println(" COMP_SPEC may also be a component name (com.foo/.myApp),");
7657 pw.println(" a partial substring in a component name, an");
7658 pw.println(" ActivityRecord hex object identifier, or");
Dianne Hackbornf9302322011-06-14 18:36:14 -07007659 pw.println(" \"all\" for all objects, or");
7660 pw.println(" \"top\" for the top activity.");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007661 pw.println(" -a: include all available server state.");
7662 pw.println(" -c: include client state.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007663 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007664 } else {
7665 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007666 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007667 }
7668
7669 // Is the caller requesting to dump a particular piece of data?
7670 if (opti < args.length) {
7671 String cmd = args[opti];
7672 opti++;
7673 if ("activities".equals(cmd) || "a".equals(cmd)) {
7674 synchronized (this) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007675 dumpActivitiesLocked(fd, pw, args, opti, true, dumpClient);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007676 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007677 return;
7678 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
7679 synchronized (this) {
7680 dumpBroadcastsLocked(fd, pw, args, opti, true);
7681 }
7682 return;
7683 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
7684 synchronized (this) {
7685 dumpPendingIntentsLocked(fd, pw, args, opti, true);
7686 }
7687 return;
7688 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
7689 synchronized (this) {
7690 dumpProcessesLocked(fd, pw, args, opti, true);
7691 }
7692 return;
Dianne Hackborn287952c2010-09-22 22:34:31 -07007693 } else if ("oom".equals(cmd) || "o".equals(cmd)) {
7694 synchronized (this) {
7695 dumpOomLocked(fd, pw, args, opti, true);
7696 }
7697 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007698 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
7699 synchronized (this) {
7700 dumpProvidersLocked(fd, pw, args, opti, true);
7701 }
7702 return;
7703 } else if ("service".equals(cmd)) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007704 String[] newArgs;
7705 String name;
7706 if (opti >= args.length) {
7707 name = null;
7708 newArgs = EMPTY_STRING_ARRAY;
7709 } else {
7710 name = args[opti];
7711 opti++;
7712 newArgs = new String[args.length - opti];
7713 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
7714 }
7715 if (!dumpService(fd, pw, name, newArgs, 0, dumpAll)) {
7716 pw.println("No services match: " + name);
7717 pw.println("Use -h for help.");
7718 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007719 return;
7720 } else if ("services".equals(cmd) || "s".equals(cmd)) {
7721 synchronized (this) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007722 dumpServicesLocked(fd, pw, args, opti, true, dumpClient);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007723 }
7724 return;
Dianne Hackborn625ac272010-09-17 18:29:22 -07007725 } else {
7726 // Dumping a single activity?
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007727 if (!dumpActivity(fd, pw, cmd, args, opti, dumpAll)) {
7728 pw.println("Bad activity command, or no activities match: " + cmd);
7729 pw.println("Use -h for help.");
Dianne Hackborn625ac272010-09-17 18:29:22 -07007730 }
Dianne Hackborn30d71892010-12-11 10:37:55 -08007731 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007732 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007733 }
7734
7735 // No piece of data specified, dump everything.
7736 synchronized (this) {
7737 boolean needSep;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007738 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007739 if (needSep) {
7740 pw.println(" ");
7741 }
7742 if (dumpAll) {
7743 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007744 }
7745 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
7746 if (needSep) {
7747 pw.println(" ");
7748 }
7749 if (dumpAll) {
7750 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007751 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007752 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007753 if (needSep) {
7754 pw.println(" ");
7755 }
7756 if (dumpAll) {
7757 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007758 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007759 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll, dumpClient);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007760 if (needSep) {
7761 pw.println(" ");
7762 }
7763 if (dumpAll) {
7764 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007765 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007766 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, dumpClient);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007767 if (needSep) {
7768 pw.println(" ");
7769 }
7770 if (dumpAll) {
7771 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007772 }
7773 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
7774 }
7775 }
7776
7777 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007778 int opti, boolean dumpAll, boolean dumpClient) {
7779 pw.println("ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)");
7780 pw.println(" Main stack:");
7781 dumpHistoryList(fd, pw, mMainStack.mHistory, " ", "Hist", true, !dumpAll, dumpClient);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007782 pw.println(" ");
7783 pw.println(" Running activities (most recent first):");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007784 dumpHistoryList(fd, pw, mMainStack.mLRUActivities, " ", "Run", false, !dumpAll, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007785 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007786 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007787 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007788 dumpHistoryList(fd, pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false,
7789 !dumpAll, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007790 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007791 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007792 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007793 pw.println(" Activities waiting to stop:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007794 dumpHistoryList(fd, pw, mMainStack.mStoppingActivities, " ", "Stop", false,
7795 !dumpAll, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007796 }
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08007797 if (mMainStack.mGoingToSleepActivities.size() > 0) {
7798 pw.println(" ");
7799 pw.println(" Activities waiting to sleep:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007800 dumpHistoryList(fd, pw, mMainStack.mGoingToSleepActivities, " ", "Sleep", false,
7801 !dumpAll, false);
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08007802 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007803 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007804 pw.println(" ");
7805 pw.println(" Activities waiting to finish:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007806 dumpHistoryList(fd, pw, mMainStack.mFinishingActivities, " ", "Fin", false,
7807 !dumpAll, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007808 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007809
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007810 pw.println(" ");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007811 if (mMainStack.mPausingActivity != null) {
7812 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
7813 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007814 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007815 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007816 if (dumpAll) {
7817 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
7818 pw.println(" mSleepTimeout: " + mMainStack.mSleepTimeout);
7819 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007820
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007821 if (mRecentTasks.size() > 0) {
7822 pw.println();
7823 pw.println(" Recent tasks:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007824
7825 final int N = mRecentTasks.size();
7826 for (int i=0; i<N; i++) {
7827 TaskRecord tr = mRecentTasks.get(i);
7828 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
7829 pw.println(tr);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007830 if (dumpAll) {
7831 mRecentTasks.get(i).dump(pw, " ");
7832 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007833 }
7834 }
7835
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007836 if (dumpAll) {
7837 pw.println(" ");
7838 pw.println(" mCurTask: " + mCurTask);
7839 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007840
7841 return true;
7842 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07007843
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007844 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7845 int opti, boolean dumpAll) {
7846 boolean needSep = false;
7847 int numPers = 0;
7848
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007849 pw.println("ACTIVITY MANAGER RUNNING PROCESSES (dumpsys activity processes)");
7850
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007851 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007852 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
7853 final int NA = procs.size();
7854 for (int ia=0; ia<NA; ia++) {
7855 if (!needSep) {
7856 pw.println(" All known processes:");
7857 needSep = true;
7858 }
7859 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007860 pw.print(r.persistent ? " *PERS*" : " *APP*");
7861 pw.print(" UID "); pw.print(procs.keyAt(ia));
7862 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007863 r.dump(pw, " ");
7864 if (r.persistent) {
7865 numPers++;
7866 }
7867 }
7868 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007869 }
7870
7871 if (mLruProcesses.size() > 0) {
7872 if (needSep) pw.println(" ");
7873 needSep = true;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007874 pw.println(" Process LRU list (most recent first):");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007875 dumpProcessOomList(pw, this, mLruProcesses, " ",
7876 "Proc", "PERS", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007877 needSep = true;
7878 }
7879
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007880 if (dumpAll) {
7881 synchronized (mPidsSelfLocked) {
7882 if (mPidsSelfLocked.size() > 0) {
7883 if (needSep) pw.println(" ");
7884 needSep = true;
7885 pw.println(" PID mappings:");
7886 for (int i=0; i<mPidsSelfLocked.size(); i++) {
7887 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
7888 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
7889 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007890 }
7891 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007892 }
7893
7894 if (mForegroundProcesses.size() > 0) {
7895 if (needSep) pw.println(" ");
7896 needSep = true;
7897 pw.println(" Foreground Processes:");
7898 for (int i=0; i<mForegroundProcesses.size(); i++) {
7899 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
7900 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007901 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007902 }
7903
7904 if (mPersistentStartingProcesses.size() > 0) {
7905 if (needSep) pw.println(" ");
7906 needSep = true;
7907 pw.println(" Persisent processes that are starting:");
7908 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007909 "Starting Norm", "Restarting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007910 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007911
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007912 if (mRemovedProcesses.size() > 0) {
7913 if (needSep) pw.println(" ");
7914 needSep = true;
7915 pw.println(" Processes that are being removed:");
7916 dumpProcessList(pw, this, mRemovedProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007917 "Removed Norm", "Removed PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007918 }
7919
7920 if (mProcessesOnHold.size() > 0) {
7921 if (needSep) pw.println(" ");
7922 needSep = true;
7923 pw.println(" Processes that are on old until the system is ready:");
7924 dumpProcessList(pw, this, mProcessesOnHold, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007925 "OnHold Norm", "OnHold PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007926 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007927
Dianne Hackborn287952c2010-09-22 22:34:31 -07007928 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007929
7930 if (mProcessCrashTimes.getMap().size() > 0) {
7931 if (needSep) pw.println(" ");
7932 needSep = true;
7933 pw.println(" Time since processes crashed:");
7934 long now = SystemClock.uptimeMillis();
7935 for (Map.Entry<String, SparseArray<Long>> procs
7936 : mProcessCrashTimes.getMap().entrySet()) {
7937 SparseArray<Long> uids = procs.getValue();
7938 final int N = uids.size();
7939 for (int i=0; i<N; i++) {
7940 pw.print(" Process "); pw.print(procs.getKey());
7941 pw.print(" uid "); pw.print(uids.keyAt(i));
7942 pw.print(": last crashed ");
7943 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007944 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007945 }
7946 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007947 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007948
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007949 if (mBadProcesses.getMap().size() > 0) {
7950 if (needSep) pw.println(" ");
7951 needSep = true;
7952 pw.println(" Bad processes:");
7953 for (Map.Entry<String, SparseArray<Long>> procs
7954 : mBadProcesses.getMap().entrySet()) {
7955 SparseArray<Long> uids = procs.getValue();
7956 final int N = uids.size();
7957 for (int i=0; i<N; i++) {
7958 pw.print(" Bad process "); pw.print(procs.getKey());
7959 pw.print(" uid "); pw.print(uids.keyAt(i));
7960 pw.print(": crashed at time ");
7961 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007962 }
7963 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007964 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007965
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007966 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007967 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007968 if (mHeavyWeightProcess != null) {
7969 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7970 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007971 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007972 if (dumpAll) {
7973 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackborn3d0724d2011-05-12 15:39:41 -07007974 if (mCompatModePackages.getPackages().size() > 0) {
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07007975 pw.println(" mScreenCompatPackages:");
7976 for (Map.Entry<String, Integer> entry
7977 : mCompatModePackages.getPackages().entrySet()) {
7978 String pkg = entry.getKey();
7979 int mode = entry.getValue();
7980 pw.print(" "); pw.print(pkg); pw.print(": ");
7981 pw.print(mode); pw.println();
7982 }
Dianne Hackbornaa9d84c2011-05-09 19:00:59 -07007983 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007984 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007985 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
7986 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
7987 || mOrigWaitForDebugger) {
7988 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
7989 + " mDebugTransient=" + mDebugTransient
7990 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
7991 }
7992 if (mAlwaysFinishActivities || mController != null) {
7993 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
7994 + " mController=" + mController);
7995 }
7996 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007997 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007998 pw.println(" mStartRunning=" + mStartRunning
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07007999 + " mProcessesReady=" + mProcessesReady
8000 + " mSystemReady=" + mSystemReady);
8001 pw.println(" mBooting=" + mBooting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008002 + " mBooted=" + mBooted
8003 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008004 pw.print(" mLastPowerCheckRealtime=");
8005 TimeUtils.formatDuration(mLastPowerCheckRealtime, pw);
8006 pw.println("");
8007 pw.print(" mLastPowerCheckUptime=");
8008 TimeUtils.formatDuration(mLastPowerCheckUptime, pw);
8009 pw.println("");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008010 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
8011 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07008012 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008013 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008014
8015 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008016 }
8017
Dianne Hackborn287952c2010-09-22 22:34:31 -07008018 boolean dumpProcessesToGc(FileDescriptor fd, PrintWriter pw, String[] args,
8019 int opti, boolean needSep, boolean dumpAll) {
8020 if (mProcessesToGc.size() > 0) {
8021 if (needSep) pw.println(" ");
8022 needSep = true;
8023 pw.println(" Processes that are waiting to GC:");
8024 long now = SystemClock.uptimeMillis();
8025 for (int i=0; i<mProcessesToGc.size(); i++) {
8026 ProcessRecord proc = mProcessesToGc.get(i);
8027 pw.print(" Process "); pw.println(proc);
8028 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
8029 pw.print(", last gced=");
8030 pw.print(now-proc.lastRequestedGc);
8031 pw.print(" ms ago, last lowMem=");
8032 pw.print(now-proc.lastLowMemory);
8033 pw.println(" ms ago");
8034
8035 }
8036 }
8037 return needSep;
8038 }
8039
8040 boolean dumpOomLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8041 int opti, boolean dumpAll) {
8042 boolean needSep = false;
8043
8044 if (mLruProcesses.size() > 0) {
8045 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>(mLruProcesses);
8046
8047 Comparator<ProcessRecord> comparator = new Comparator<ProcessRecord>() {
8048 @Override
8049 public int compare(ProcessRecord object1, ProcessRecord object2) {
8050 if (object1.setAdj != object2.setAdj) {
8051 return object1.setAdj > object2.setAdj ? -1 : 1;
8052 }
8053 if (object1.setSchedGroup != object2.setSchedGroup) {
8054 return object1.setSchedGroup > object2.setSchedGroup ? -1 : 1;
8055 }
8056 if (object1.keeping != object2.keeping) {
8057 return object1.keeping ? -1 : 1;
8058 }
8059 if (object1.pid != object2.pid) {
8060 return object1.pid > object2.pid ? -1 : 1;
8061 }
8062 return 0;
8063 }
8064 };
8065
8066 Collections.sort(procs, comparator);
8067
8068 if (needSep) pw.println(" ");
8069 needSep = true;
8070 pw.println(" Process OOM control:");
8071 dumpProcessOomList(pw, this, procs, " ",
8072 "Proc", "PERS", true);
8073 needSep = true;
8074 }
8075
8076 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
8077
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008078 pw.println();
Dianne Hackborn287952c2010-09-22 22:34:31 -07008079 pw.println(" mHomeProcess: " + mHomeProcess);
8080 if (mHeavyWeightProcess != null) {
8081 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
8082 }
8083
8084 return true;
8085 }
8086
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008087 /**
8088 * There are three ways to call this:
8089 * - no service specified: dump all the services
8090 * - a flattened component name that matched an existing service was specified as the
8091 * first arg: dump that one service
8092 * - the first arg isn't the flattened component name of an existing service:
8093 * dump all services whose component contains the first arg as a substring
8094 */
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008095 protected boolean dumpService(FileDescriptor fd, PrintWriter pw, String name, String[] args,
8096 int opti, boolean dumpAll) {
8097 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008098
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008099 if ("all".equals(name)) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07008100 synchronized (this) {
8101 for (ServiceRecord r1 : mServices.values()) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008102 services.add(r1);
8103 }
8104 }
8105 } else {
8106 ComponentName componentName = name != null
8107 ? ComponentName.unflattenFromString(name) : null;
8108 int objectId = 0;
8109 if (componentName == null) {
8110 // Not a '/' separated full component name; maybe an object ID?
8111 try {
8112 objectId = Integer.parseInt(name, 16);
8113 name = null;
8114 componentName = null;
8115 } catch (RuntimeException e) {
8116 }
8117 }
8118
8119 synchronized (this) {
8120 for (ServiceRecord r1 : mServices.values()) {
8121 if (componentName != null) {
8122 if (r1.name.equals(componentName)) {
8123 services.add(r1);
8124 }
8125 } else if (name != null) {
8126 if (r1.name.flattenToString().contains(name)) {
8127 services.add(r1);
8128 }
8129 } else if (System.identityHashCode(r1) == objectId) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07008130 services.add(r1);
8131 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008132 }
8133 }
8134 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008135
8136 if (services.size() <= 0) {
8137 return false;
8138 }
8139
8140 boolean needSep = false;
8141 for (int i=0; i<services.size(); i++) {
8142 if (needSep) {
8143 pw.println();
8144 }
8145 needSep = true;
8146 dumpService("", fd, pw, services.get(i), args, dumpAll);
8147 }
8148 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008149 }
8150
8151 /**
8152 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
8153 * there is a thread associated with the service.
8154 */
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008155 private void dumpService(String prefix, FileDescriptor fd, PrintWriter pw,
8156 final ServiceRecord r, String[] args, boolean dumpAll) {
8157 String innerPrefix = prefix + " ";
8158 synchronized (this) {
8159 pw.print(prefix); pw.print("SERVICE ");
8160 pw.print(r.shortName); pw.print(" ");
8161 pw.print(Integer.toHexString(System.identityHashCode(r)));
8162 pw.print(" pid=");
8163 if (r.app != null) pw.println(r.app.pid);
8164 else pw.println("(not running)");
8165 if (dumpAll) {
8166 r.dump(pw, innerPrefix);
8167 }
8168 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008169 if (r.app != null && r.app.thread != null) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008170 pw.print(prefix); pw.println(" Client:");
8171 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008172 try {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008173 TransferPipe tp = new TransferPipe();
8174 try {
8175 r.app.thread.dumpService(tp.getWriteFd().getFileDescriptor(), r, args);
8176 tp.setBufferPrefix(prefix + " ");
8177 tp.go(fd);
8178 } finally {
8179 tp.kill();
8180 }
8181 } catch (IOException e) {
8182 pw.println(prefix + " Failure while dumping the service: " + e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008183 } catch (RemoteException e) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008184 pw.println(prefix + " Got a RemoteException while dumping the service");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008185 }
8186 }
8187 }
8188
Dianne Hackborn625ac272010-09-17 18:29:22 -07008189 /**
8190 * There are three things that cmd can be:
8191 * - a flattened component name that matched an existing activity
8192 * - the cmd arg isn't the flattened component name of an existing activity:
8193 * dump all activity whose component contains the cmd as a substring
8194 * - A hex number of the ActivityRecord object instance.
8195 */
8196 protected boolean dumpActivity(FileDescriptor fd, PrintWriter pw, String name, String[] args,
8197 int opti, boolean dumpAll) {
Dianne Hackborn625ac272010-09-17 18:29:22 -07008198 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008199
8200 if ("all".equals(name)) {
8201 synchronized (this) {
8202 for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
Dianne Hackborn625ac272010-09-17 18:29:22 -07008203 activities.add(r1);
8204 }
8205 }
Dianne Hackbornf9302322011-06-14 18:36:14 -07008206 } else if ("top".equals(name)) {
8207 synchronized (this) {
8208 final int N = mMainStack.mHistory.size();
8209 if (N > 0) {
8210 activities.add((ActivityRecord)mMainStack.mHistory.get(N-1));
8211 }
8212 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008213 } else {
8214 ComponentName componentName = ComponentName.unflattenFromString(name);
8215 int objectId = 0;
8216 if (componentName == null) {
8217 // Not a '/' separated full component name; maybe an object ID?
8218 try {
8219 objectId = Integer.parseInt(name, 16);
8220 name = null;
8221 componentName = null;
8222 } catch (RuntimeException e) {
8223 }
8224 }
8225
8226 synchronized (this) {
8227 for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
8228 if (componentName != null) {
8229 if (r1.intent.getComponent().equals(componentName)) {
8230 activities.add(r1);
8231 }
8232 } else if (name != null) {
8233 if (r1.intent.getComponent().flattenToString().contains(name)) {
8234 activities.add(r1);
8235 }
8236 } else if (System.identityHashCode(r1) == objectId) {
8237 activities.add(r1);
8238 }
8239 }
8240 }
Dianne Hackborn625ac272010-09-17 18:29:22 -07008241 }
8242
8243 if (activities.size() <= 0) {
8244 return false;
8245 }
8246
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008247 String[] newArgs = new String[args.length - opti];
8248 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
8249
Dianne Hackborn30d71892010-12-11 10:37:55 -08008250 TaskRecord lastTask = null;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008251 boolean needSep = false;
Dianne Hackborn30d71892010-12-11 10:37:55 -08008252 for (int i=activities.size()-1; i>=0; i--) {
8253 ActivityRecord r = (ActivityRecord)activities.get(i);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008254 if (needSep) {
8255 pw.println();
8256 }
8257 needSep = true;
8258 synchronized (this) {
8259 if (lastTask != r.task) {
8260 lastTask = r.task;
8261 pw.print("TASK "); pw.print(lastTask.affinity);
8262 pw.print(" id="); pw.println(lastTask.taskId);
8263 if (dumpAll) {
8264 lastTask.dump(pw, " ");
8265 }
Dianne Hackborn30d71892010-12-11 10:37:55 -08008266 }
8267 }
8268 dumpActivity(" ", fd, pw, activities.get(i), newArgs, dumpAll);
Dianne Hackborn625ac272010-09-17 18:29:22 -07008269 }
8270 return true;
8271 }
8272
8273 /**
8274 * Invokes IApplicationThread.dumpActivity() on the thread of the specified activity if
8275 * there is a thread associated with the activity.
8276 */
Dianne Hackborn30d71892010-12-11 10:37:55 -08008277 private void dumpActivity(String prefix, FileDescriptor fd, PrintWriter pw,
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008278 final ActivityRecord r, String[] args, boolean dumpAll) {
8279 String innerPrefix = prefix + " ";
Dianne Hackborn30d71892010-12-11 10:37:55 -08008280 synchronized (this) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008281 pw.print(prefix); pw.print("ACTIVITY "); pw.print(r.shortComponentName);
8282 pw.print(" "); pw.print(Integer.toHexString(System.identityHashCode(r)));
8283 pw.print(" pid=");
Dianne Hackborn30d71892010-12-11 10:37:55 -08008284 if (r.app != null) pw.println(r.app.pid);
8285 else pw.println("(not running)");
8286 if (dumpAll) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008287 r.dump(pw, innerPrefix);
Dianne Hackborn625ac272010-09-17 18:29:22 -07008288 }
Dianne Hackborn625ac272010-09-17 18:29:22 -07008289 }
8290 if (r.app != null && r.app.thread != null) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008291 // flush anything that is already in the PrintWriter since the thread is going
8292 // to write to the file descriptor directly
8293 pw.flush();
Dianne Hackborn625ac272010-09-17 18:29:22 -07008294 try {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008295 TransferPipe tp = new TransferPipe();
8296 try {
8297 r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(), r,
8298 innerPrefix, args);
8299 tp.go(fd);
8300 } finally {
8301 tp.kill();
8302 }
8303 } catch (IOException e) {
8304 pw.println(innerPrefix + "Failure while dumping the activity: " + e);
Dianne Hackborn625ac272010-09-17 18:29:22 -07008305 } catch (RemoteException e) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008306 pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
Dianne Hackborn625ac272010-09-17 18:29:22 -07008307 }
8308 }
8309 }
8310
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008311 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8312 int opti, boolean dumpAll) {
8313 boolean needSep = false;
8314
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008315 pw.println("ACTIVITY MANAGER BROADCAST STATE (dumpsys activity broadcasts)");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008316 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008317 if (mRegisteredReceivers.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008318 pw.println(" Registered Receivers:");
8319 Iterator it = mRegisteredReceivers.values().iterator();
8320 while (it.hasNext()) {
8321 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008322 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008323 r.dump(pw, " ");
8324 }
8325 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008326
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008327 pw.println();
8328 pw.println(" Receiver Resolver Table:");
8329 mReceiverResolver.dump(pw, null, " ", null, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008330 needSep = true;
8331 }
8332
8333 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
8334 || mPendingBroadcast != null) {
8335 if (mParallelBroadcasts.size() > 0) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008336 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008337 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008338 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008339 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
8340 pw.println(" Broadcast #" + i + ":");
8341 mParallelBroadcasts.get(i).dump(pw, " ");
8342 }
8343 if (mOrderedBroadcasts.size() > 0) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008344 pw.println();
Dianne Hackborn399cccb2010-04-13 22:57:49 -07008345 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008346 }
8347 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
8348 pw.println(" Serialized Broadcast #" + i + ":");
8349 mOrderedBroadcasts.get(i).dump(pw, " ");
8350 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008351 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008352 pw.println(" Pending broadcast:");
8353 if (mPendingBroadcast != null) {
8354 mPendingBroadcast.dump(pw, " ");
8355 } else {
8356 pw.println(" (null)");
8357 }
8358 needSep = true;
8359 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008360
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008361 if (needSep) {
8362 pw.println();
8363 }
8364 pw.println(" Historical broadcasts:");
8365 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
8366 BroadcastRecord r = mBroadcastHistory[i];
8367 if (r == null) {
8368 break;
8369 }
8370 if (dumpAll) {
8371 pw.print(" Historical Broadcast #"); pw.print(i); pw.println(":");
8372 r.dump(pw, " ");
8373 } else {
8374 if (i >= 50) {
8375 pw.println(" ...");
Dianne Hackborn12527f92009-11-11 17:39:50 -08008376 break;
8377 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008378 pw.print(" #"); pw.print(i); pw.print(": "); pw.println(r);
Dianne Hackborn12527f92009-11-11 17:39:50 -08008379 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008380 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008381 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008382
8383 if (mStickyBroadcasts != null) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008384 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008385 pw.println(" Sticky broadcasts:");
8386 StringBuilder sb = new StringBuilder(128);
8387 for (Map.Entry<String, ArrayList<Intent>> ent
8388 : mStickyBroadcasts.entrySet()) {
8389 pw.print(" * Sticky action "); pw.print(ent.getKey());
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008390 if (dumpAll) {
8391 pw.println(":");
8392 ArrayList<Intent> intents = ent.getValue();
8393 final int N = intents.size();
8394 for (int i=0; i<N; i++) {
8395 sb.setLength(0);
8396 sb.append(" Intent: ");
8397 intents.get(i).toShortString(sb, true, false);
8398 pw.println(sb.toString());
8399 Bundle bundle = intents.get(i).getExtras();
8400 if (bundle != null) {
8401 pw.print(" ");
8402 pw.println(bundle.toString());
8403 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008404 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008405 } else {
8406 pw.println("");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008407 }
8408 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008409 needSep = true;
8410 }
8411
8412 if (dumpAll) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008413 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008414 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008415 pw.println(" mHandler:");
8416 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008417 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008418 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008419
8420 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008421 }
8422
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008423 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008424 int opti, boolean dumpAll, boolean dumpClient) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008425 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008426
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008427 pw.println("ACTIVITY MANAGER SERVICES (dumpsys activity services)");
8428 if (mServices.size() > 0) {
8429 pw.println(" Active services:");
8430 long nowReal = SystemClock.elapsedRealtime();
8431 Iterator<ServiceRecord> it = mServices.values().iterator();
8432 needSep = false;
8433 while (it.hasNext()) {
8434 ServiceRecord r = it.next();
8435 if (needSep) {
8436 pw.println();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008437 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008438 pw.print(" * "); pw.println(r);
8439 if (dumpAll) {
8440 r.dump(pw, " ");
8441 needSep = true;
8442 } else {
8443 pw.print(" app="); pw.println(r.app);
8444 pw.print(" created=");
8445 TimeUtils.formatDuration(r.createTime, nowReal, pw);
8446 pw.print(" started="); pw.print(r.startRequested);
8447 pw.print(" connections="); pw.println(r.connections.size());
8448 }
8449 if (dumpClient && r.app != null && r.app.thread != null) {
8450 pw.println(" Client:");
8451 pw.flush();
8452 try {
8453 TransferPipe tp = new TransferPipe();
8454 try {
8455 r.app.thread.dumpService(
8456 tp.getWriteFd().getFileDescriptor(), r, args);
8457 tp.setBufferPrefix(" ");
8458 // Short timeout, since blocking here can
8459 // deadlock with the application.
8460 tp.go(fd, 2000);
8461 } finally {
8462 tp.kill();
8463 }
8464 } catch (IOException e) {
8465 pw.println(" Failure while dumping the service: " + e);
8466 } catch (RemoteException e) {
8467 pw.println(" Got a RemoteException while dumping the service");
8468 }
8469 needSep = true;
8470 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008471 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008472 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008473 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008474
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008475 if (mPendingServices.size() > 0) {
8476 if (needSep) pw.println(" ");
8477 pw.println(" Pending services:");
8478 for (int i=0; i<mPendingServices.size(); i++) {
8479 ServiceRecord r = mPendingServices.get(i);
8480 pw.print(" * Pending "); pw.println(r);
8481 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008482 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008483 needSep = true;
8484 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008485
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008486 if (mRestartingServices.size() > 0) {
8487 if (needSep) pw.println(" ");
8488 pw.println(" Restarting services:");
8489 for (int i=0; i<mRestartingServices.size(); i++) {
8490 ServiceRecord r = mRestartingServices.get(i);
8491 pw.print(" * Restarting "); pw.println(r);
8492 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008493 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008494 needSep = true;
8495 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008496
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008497 if (mStoppingServices.size() > 0) {
8498 if (needSep) pw.println(" ");
8499 pw.println(" Stopping services:");
8500 for (int i=0; i<mStoppingServices.size(); i++) {
8501 ServiceRecord r = mStoppingServices.get(i);
8502 pw.print(" * Stopping "); pw.println(r);
8503 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008504 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008505 needSep = true;
8506 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008507
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008508 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008509 if (mServiceConnections.size() > 0) {
8510 if (needSep) pw.println(" ");
8511 pw.println(" Connection bindings to services:");
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008512 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008513 = mServiceConnections.values().iterator();
8514 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008515 ArrayList<ConnectionRecord> r = it.next();
8516 for (int i=0; i<r.size(); i++) {
8517 pw.print(" * "); pw.println(r.get(i));
8518 r.get(i).dump(pw, " ");
8519 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008520 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008521 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008522 }
8523 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008524
8525 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008526 }
8527
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008528 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8529 int opti, boolean dumpAll) {
8530 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008531
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008532 pw.println("ACTIVITY MANAGER CONTENT PROVIDERS (dumpsys activity providers)");
8533 if (mProvidersByClass.size() > 0) {
8534 if (needSep) pw.println(" ");
8535 pw.println(" Published content providers (by class):");
8536 Iterator<Map.Entry<String, ContentProviderRecord>> it
8537 = mProvidersByClass.entrySet().iterator();
8538 while (it.hasNext()) {
8539 Map.Entry<String, ContentProviderRecord> e = it.next();
8540 ContentProviderRecord r = e.getValue();
8541 if (dumpAll) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008542 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008543 r.dump(pw, " ");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008544 } else {
8545 pw.print(" * "); pw.print(r.name.toShortString());
8546 if (r.app != null) {
8547 pw.println(":");
8548 pw.print(" "); pw.println(r.app);
8549 } else {
8550 pw.println();
8551 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008552 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008553 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008554 needSep = true;
8555 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008556
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008557 if (dumpAll) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008558 if (mProvidersByName.size() > 0) {
8559 pw.println(" ");
8560 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -07008561 Iterator<Map.Entry<String, ContentProviderRecord>> it
8562 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008563 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008564 Map.Entry<String, ContentProviderRecord> e = it.next();
8565 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008566 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
8567 pw.println(r);
8568 }
8569 needSep = true;
8570 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008571 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008572
8573 if (mLaunchingProviders.size() > 0) {
8574 if (needSep) pw.println(" ");
8575 pw.println(" Launching content providers:");
8576 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
8577 pw.print(" Launching #"); pw.print(i); pw.print(": ");
8578 pw.println(mLaunchingProviders.get(i));
8579 }
8580 needSep = true;
8581 }
8582
8583 if (mGrantedUriPermissions.size() > 0) {
8584 pw.println();
8585 pw.println("Granted Uri Permissions:");
8586 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
8587 int uid = mGrantedUriPermissions.keyAt(i);
8588 HashMap<Uri, UriPermission> perms
8589 = mGrantedUriPermissions.valueAt(i);
8590 pw.print(" * UID "); pw.print(uid);
8591 pw.println(" holds:");
8592 for (UriPermission perm : perms.values()) {
8593 pw.print(" "); pw.println(perm);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008594 if (dumpAll) {
8595 perm.dump(pw, " ");
8596 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008597 }
8598 }
8599 needSep = true;
8600 }
8601
8602 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008603 }
8604
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008605 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8606 int opti, boolean dumpAll) {
8607 boolean needSep = false;
8608
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008609 if (this.mIntentSenderRecords.size() > 0) {
8610 pw.println("ACTIVITY MANAGER PENDING INTENTS (dumpsys activity intents)");
8611 Iterator<WeakReference<PendingIntentRecord>> it
8612 = mIntentSenderRecords.values().iterator();
8613 while (it.hasNext()) {
8614 WeakReference<PendingIntentRecord> ref = it.next();
8615 PendingIntentRecord rec = ref != null ? ref.get(): null;
8616 needSep = true;
8617 if (rec != null) {
8618 pw.print(" * "); pw.println(rec);
8619 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008620 rec.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008621 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008622 } else {
8623 pw.print(" * "); pw.println(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008624 }
8625 }
8626 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008627
8628 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008629 }
8630
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008631 private static final void dumpHistoryList(FileDescriptor fd, PrintWriter pw, List list,
8632 String prefix, String label, boolean complete, boolean brief, boolean client) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008633 TaskRecord lastTask = null;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008634 boolean needNL = false;
8635 final String innerPrefix = prefix + " ";
8636 final String[] args = new String[0];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008637 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008638 final ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackbornf26fd992011-04-08 18:14:09 -07008639 final boolean full = !brief && (complete || !r.isInHistory());
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008640 if (needNL) {
8641 pw.println(" ");
8642 needNL = false;
8643 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008644 if (lastTask != r.task) {
8645 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008646 pw.print(prefix);
8647 pw.print(full ? "* " : " ");
8648 pw.println(lastTask);
8649 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008650 lastTask.dump(pw, prefix + " ");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008651 } else if (complete) {
8652 // Complete + brief == give a summary. Isn't that obvious?!?
8653 if (lastTask.intent != null) {
8654 pw.print(prefix); pw.print(" "); pw.println(lastTask.intent);
8655 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008656 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008657 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008658 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
8659 pw.print(" #"); pw.print(i); pw.print(": ");
8660 pw.println(r);
8661 if (full) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008662 r.dump(pw, innerPrefix);
8663 } else if (complete) {
8664 // Complete + brief == give a summary. Isn't that obvious?!?
8665 pw.print(innerPrefix); pw.println(r.intent);
8666 if (r.app != null) {
8667 pw.print(innerPrefix); pw.println(r.app);
8668 }
8669 }
8670 if (client && r.app != null && r.app.thread != null) {
8671 // flush anything that is already in the PrintWriter since the thread is going
8672 // to write to the file descriptor directly
8673 pw.flush();
8674 try {
8675 TransferPipe tp = new TransferPipe();
8676 try {
8677 r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(), r,
8678 innerPrefix, args);
8679 // Short timeout, since blocking here can
8680 // deadlock with the application.
8681 tp.go(fd, 2000);
8682 } finally {
8683 tp.kill();
8684 }
8685 } catch (IOException e) {
8686 pw.println(innerPrefix + "Failure while dumping the activity: " + e);
8687 } catch (RemoteException e) {
8688 pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
8689 }
8690 needNL = true;
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008691 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008692 }
8693 }
8694
Dianne Hackborn09c916b2009-12-08 14:50:51 -08008695 private static String buildOomTag(String prefix, String space, int val, int base) {
8696 if (val == base) {
8697 if (space == null) return prefix;
8698 return prefix + " ";
8699 }
8700 return prefix + "+" + Integer.toString(val-base);
8701 }
8702
8703 private static final int dumpProcessList(PrintWriter pw,
8704 ActivityManagerService service, List list,
Dianne Hackborn287952c2010-09-22 22:34:31 -07008705 String prefix, String normalLabel, String persistentLabel) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008706 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07008707 final int N = list.size()-1;
8708 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008709 ProcessRecord r = (ProcessRecord)list.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008710 pw.println(String.format("%s%s #%2d: %s",
8711 prefix, (r.persistent ? persistentLabel : normalLabel),
8712 i, r.toString()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008713 if (r.persistent) {
8714 numPers++;
8715 }
8716 }
8717 return numPers;
8718 }
8719
Dianne Hackborn287952c2010-09-22 22:34:31 -07008720 private static final void dumpProcessOomList(PrintWriter pw,
8721 ActivityManagerService service, List<ProcessRecord> list,
8722 String prefix, String normalLabel, String persistentLabel,
8723 boolean inclDetails) {
8724
8725 final long curRealtime = SystemClock.elapsedRealtime();
8726 final long realtimeSince = curRealtime - service.mLastPowerCheckRealtime;
8727 final long curUptime = SystemClock.uptimeMillis();
8728 final long uptimeSince = curUptime - service.mLastPowerCheckUptime;
8729
8730 final int N = list.size()-1;
8731 for (int i=N; i>=0; i--) {
8732 ProcessRecord r = list.get(i);
8733 String oomAdj;
8734 if (r.setAdj >= EMPTY_APP_ADJ) {
8735 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
8736 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
8737 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
8738 } else if (r.setAdj >= HOME_APP_ADJ) {
8739 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
8740 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
8741 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
8742 } else if (r.setAdj >= BACKUP_APP_ADJ) {
8743 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
8744 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
8745 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
8746 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
8747 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
8748 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
8749 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
8750 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
8751 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
8752 } else if (r.setAdj >= CORE_SERVER_ADJ) {
8753 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
8754 } else if (r.setAdj >= SYSTEM_ADJ) {
8755 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
8756 } else {
8757 oomAdj = Integer.toString(r.setAdj);
8758 }
8759 String schedGroup;
8760 switch (r.setSchedGroup) {
8761 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
8762 schedGroup = "B";
8763 break;
8764 case Process.THREAD_GROUP_DEFAULT:
8765 schedGroup = "F";
8766 break;
8767 default:
8768 schedGroup = Integer.toString(r.setSchedGroup);
8769 break;
8770 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07008771 String foreground;
8772 if (r.foregroundActivities) {
8773 foreground = "A";
8774 } else if (r.foregroundServices) {
8775 foreground = "S";
8776 } else {
8777 foreground = " ";
8778 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -07008779 pw.println(String.format("%s%s #%2d: adj=%s/%s%s trm=%2d %s (%s)",
Dianne Hackborn287952c2010-09-22 22:34:31 -07008780 prefix, (r.persistent ? persistentLabel : normalLabel),
Dianne Hackbornce86ba82011-07-13 19:33:41 -07008781 N-i, oomAdj, schedGroup, foreground, r.trimMemoryLevel,
8782 r.toShortString(), r.adjType));
Dianne Hackborn287952c2010-09-22 22:34:31 -07008783 if (r.adjSource != null || r.adjTarget != null) {
8784 pw.print(prefix);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008785 pw.print(" ");
Dianne Hackborn287952c2010-09-22 22:34:31 -07008786 if (r.adjTarget instanceof ComponentName) {
8787 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
8788 } else if (r.adjTarget != null) {
8789 pw.print(r.adjTarget.toString());
8790 } else {
8791 pw.print("{null}");
8792 }
8793 pw.print("<=");
8794 if (r.adjSource instanceof ProcessRecord) {
8795 pw.print("Proc{");
8796 pw.print(((ProcessRecord)r.adjSource).toShortString());
8797 pw.println("}");
8798 } else if (r.adjSource != null) {
8799 pw.println(r.adjSource.toString());
8800 } else {
8801 pw.println("{null}");
8802 }
8803 }
8804 if (inclDetails) {
8805 pw.print(prefix);
8806 pw.print(" ");
8807 pw.print("oom: max="); pw.print(r.maxAdj);
8808 pw.print(" hidden="); pw.print(r.hiddenAdj);
8809 pw.print(" curRaw="); pw.print(r.curRawAdj);
8810 pw.print(" setRaw="); pw.print(r.setRawAdj);
8811 pw.print(" cur="); pw.print(r.curAdj);
8812 pw.print(" set="); pw.println(r.setAdj);
8813 pw.print(prefix);
8814 pw.print(" ");
8815 pw.print("keeping="); pw.print(r.keeping);
8816 pw.print(" hidden="); pw.print(r.hidden);
8817 pw.print(" empty="); pw.println(r.empty);
8818
8819 if (!r.keeping) {
8820 if (r.lastWakeTime != 0) {
8821 long wtime;
8822 BatteryStatsImpl stats = service.mBatteryStatsService.getActiveStatistics();
8823 synchronized (stats) {
8824 wtime = stats.getProcessWakeTime(r.info.uid,
8825 r.pid, curRealtime);
8826 }
8827 long timeUsed = wtime - r.lastWakeTime;
8828 pw.print(prefix);
8829 pw.print(" ");
8830 pw.print("keep awake over ");
8831 TimeUtils.formatDuration(realtimeSince, pw);
8832 pw.print(" used ");
8833 TimeUtils.formatDuration(timeUsed, pw);
8834 pw.print(" (");
8835 pw.print((timeUsed*100)/realtimeSince);
8836 pw.println("%)");
8837 }
8838 if (r.lastCpuTime != 0) {
8839 long timeUsed = r.curCpuTime - r.lastCpuTime;
8840 pw.print(prefix);
8841 pw.print(" ");
8842 pw.print("run cpu over ");
8843 TimeUtils.formatDuration(uptimeSince, pw);
8844 pw.print(" used ");
8845 TimeUtils.formatDuration(timeUsed, pw);
8846 pw.print(" (");
8847 pw.print((timeUsed*100)/uptimeSince);
8848 pw.println("%)");
8849 }
8850 }
8851 }
8852 }
8853 }
8854
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008855 ArrayList<ProcessRecord> collectProcesses(PrintWriter pw, String[] args) {
8856 ArrayList<ProcessRecord> procs;
8857 synchronized (this) {
8858 if (args != null && args.length > 0
8859 && args[0].charAt(0) != '-') {
8860 procs = new ArrayList<ProcessRecord>();
8861 int pid = -1;
8862 try {
8863 pid = Integer.parseInt(args[0]);
8864 } catch (NumberFormatException e) {
8865
8866 }
8867 for (int i=mLruProcesses.size()-1; i>=0; i--) {
8868 ProcessRecord proc = mLruProcesses.get(i);
8869 if (proc.pid == pid) {
8870 procs.add(proc);
8871 } else if (proc.processName.equals(args[0])) {
8872 procs.add(proc);
8873 }
8874 }
8875 if (procs.size() <= 0) {
8876 pw.println("No process found for: " + args[0]);
8877 return null;
8878 }
8879 } else {
8880 procs = new ArrayList<ProcessRecord>(mLruProcesses);
8881 }
8882 }
8883 return procs;
8884 }
8885
8886 final void dumpGraphicsHardwareUsage(FileDescriptor fd,
8887 PrintWriter pw, String[] args) {
8888 ArrayList<ProcessRecord> procs = collectProcesses(pw, args);
8889 if (procs == null) {
8890 return;
8891 }
8892
8893 long uptime = SystemClock.uptimeMillis();
8894 long realtime = SystemClock.elapsedRealtime();
8895 pw.println("Applications Graphics Acceleration Info:");
8896 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
8897
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008898 for (int i = procs.size() - 1 ; i >= 0 ; i--) {
8899 ProcessRecord r = procs.get(i);
Chet Haase9c1e23b2011-03-24 10:51:31 -07008900 if (r.thread != null) {
8901 pw.println("\n** Graphics info for pid " + r.pid + " [" + r.processName + "] **");
8902 pw.flush();
8903 try {
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07008904 TransferPipe tp = new TransferPipe();
8905 try {
8906 r.thread.dumpGfxInfo(tp.getWriteFd().getFileDescriptor(), args);
8907 tp.go(fd);
8908 } finally {
8909 tp.kill();
8910 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008911 } catch (IOException e) {
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07008912 pw.println("Failure while dumping the app: " + r);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008913 pw.flush();
Chet Haase9c1e23b2011-03-24 10:51:31 -07008914 } catch (RemoteException e) {
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07008915 pw.println("Got a RemoteException while dumping the app " + r);
Chet Haase9c1e23b2011-03-24 10:51:31 -07008916 pw.flush();
8917 }
8918 }
8919 }
Chet Haase9c1e23b2011-03-24 10:51:31 -07008920 }
8921
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07008922 final static class MemItem {
8923 final String label;
8924 final long pss;
8925
8926 public MemItem(String _label, long _pss) {
8927 label = _label;
8928 pss = _pss;
8929 }
8930 }
8931
8932 final void dumpMemItems(PrintWriter pw, String prefix, ArrayList<MemItem> items) {
8933 Collections.sort(items, new Comparator<MemItem>() {
8934 @Override
8935 public int compare(MemItem lhs, MemItem rhs) {
8936 if (lhs.pss < rhs.pss) {
8937 return 1;
8938 } else if (lhs.pss > rhs.pss) {
8939 return -1;
8940 }
8941 return 0;
8942 }
8943 });
8944
8945 for (int i=0; i<items.size(); i++) {
8946 MemItem mi = items.get(i);
8947 pw.print(prefix); pw.printf("%8d Kb: ", mi.pss); pw.println(mi.label);
8948 }
8949 }
8950
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008951 final void dumpApplicationMemoryUsage(FileDescriptor fd,
8952 PrintWriter pw, String prefix, String[] args) {
8953 ArrayList<ProcessRecord> procs = collectProcesses(pw, args);
8954 if (procs == null) {
8955 return;
8956 }
8957
Dianne Hackborn6447ca32009-04-07 19:50:08 -07008958 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008959 long uptime = SystemClock.uptimeMillis();
8960 long realtime = SystemClock.elapsedRealtime();
8961
8962 if (isCheckinRequest) {
8963 // short checkin version
8964 pw.println(uptime + "," + realtime);
8965 pw.flush();
8966 } else {
8967 pw.println("Applications Memory Usage (kB):");
8968 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
8969 }
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07008970
8971 ArrayList<MemItem> procMems = new ArrayList<MemItem>();
8972 long nativePss=0, dalvikPss=0, otherPss=0;
8973 long[] miscPss = new long[Debug.MemoryInfo.NUM_OTHER_STATS];
8974
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008975 for (int i = procs.size() - 1 ; i >= 0 ; i--) {
8976 ProcessRecord r = procs.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008977 if (r.thread != null) {
8978 if (!isCheckinRequest) {
8979 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
8980 pw.flush();
8981 }
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07008982 Debug.MemoryInfo mi = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008983 try {
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07008984 mi = r.thread.dumpMemInfo(fd, args);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008985 } catch (RemoteException e) {
8986 if (!isCheckinRequest) {
8987 pw.println("Got RemoteException!");
8988 pw.flush();
8989 }
8990 }
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07008991 if (!isCheckinRequest && mi != null) {
8992 procMems.add(new MemItem(r.processName + " (pid " + r.pid + ")",
8993 mi.getTotalPss()));
8994
8995 nativePss += mi.nativePss;
8996 dalvikPss += mi.dalvikPss;
8997 otherPss += mi.otherPss;
8998 for (int j=0; j<Debug.MemoryInfo.NUM_OTHER_STATS; j++) {
8999 long mem = mi.getOtherPss(j);
9000 miscPss[j] += mem;
9001 otherPss -= mem;
9002 }
9003 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009004 }
9005 }
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009006
9007 if (!isCheckinRequest && procs.size() > 1) {
9008 ArrayList<MemItem> catMems = new ArrayList<MemItem>();
9009
9010 catMems.add(new MemItem("Native", nativePss));
9011 catMems.add(new MemItem("Dalvik", dalvikPss));
9012 catMems.add(new MemItem("Unknown", otherPss));
9013 for (int j=0; j<Debug.MemoryInfo.NUM_OTHER_STATS; j++) {
9014 catMems.add(new MemItem(Debug.MemoryInfo.getOtherLabel(j), miscPss[j]));
9015 }
9016
9017 pw.println();
9018 pw.println("Total PSS by process:");
9019 dumpMemItems(pw, " ", procMems);
9020 pw.println();
9021 pw.println("Total PSS by category:");
9022 dumpMemItems(pw, " ", catMems);
9023 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009024 }
9025
9026 /**
9027 * Searches array of arguments for the specified string
9028 * @param args array of argument strings
9029 * @param value value to search for
9030 * @return true if the value is contained in the array
9031 */
9032 private static boolean scanArgs(String[] args, String value) {
9033 if (args != null) {
9034 for (String arg : args) {
9035 if (value.equals(arg)) {
9036 return true;
9037 }
9038 }
9039 }
9040 return false;
9041 }
9042
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009043 private final void killServicesLocked(ProcessRecord app,
9044 boolean allowRestart) {
9045 // Report disconnected services.
9046 if (false) {
9047 // XXX we are letting the client link to the service for
9048 // death notifications.
9049 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009050 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009051 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009052 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009053 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009054 Iterator<ArrayList<ConnectionRecord>> jt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009055 = r.connections.values().iterator();
9056 while (jt.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009057 ArrayList<ConnectionRecord> cl = jt.next();
9058 for (int i=0; i<cl.size(); i++) {
9059 ConnectionRecord c = cl.get(i);
9060 if (c.binding.client != app) {
9061 try {
9062 //c.conn.connected(r.className, null);
9063 } catch (Exception e) {
9064 // todo: this should be asynchronous!
9065 Slog.w(TAG, "Exception thrown disconnected servce "
9066 + r.shortName
9067 + " from app " + app.processName, e);
9068 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009069 }
9070 }
9071 }
9072 }
9073 }
9074 }
9075 }
9076
9077 // Clean up any connections this application has to other services.
9078 if (app.connections.size() > 0) {
9079 Iterator<ConnectionRecord> it = app.connections.iterator();
9080 while (it.hasNext()) {
9081 ConnectionRecord r = it.next();
9082 removeConnectionLocked(r, app, null);
9083 }
9084 }
9085 app.connections.clear();
9086
9087 if (app.services.size() != 0) {
9088 // Any services running in the application need to be placed
9089 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07009090 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009091 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009092 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009093 synchronized (sr.stats.getBatteryStats()) {
9094 sr.stats.stopLaunchedLocked();
9095 }
9096 sr.app = null;
9097 sr.executeNesting = 0;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009098 if (mStoppingServices.remove(sr)) {
9099 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
9100 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009101
9102 boolean hasClients = sr.bindings.size() > 0;
9103 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009104 Iterator<IntentBindRecord> bindings
9105 = sr.bindings.values().iterator();
9106 while (bindings.hasNext()) {
9107 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009108 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009109 + ": shouldUnbind=" + b.hasBound);
9110 b.binder = null;
9111 b.requested = b.received = b.hasBound = false;
9112 }
9113 }
9114
Dianne Hackborn070783f2010-12-29 16:46:28 -08009115 if (sr.crashCount >= 2 && (sr.serviceInfo.applicationInfo.flags
9116 &ApplicationInfo.FLAG_PERSISTENT) == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009117 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009118 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009119 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009120 sr.crashCount, sr.shortName, app.pid);
9121 bringDownServiceLocked(sr, true);
9122 } else if (!allowRestart) {
9123 bringDownServiceLocked(sr, true);
9124 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009125 boolean canceled = scheduleServiceRestartLocked(sr, true);
9126
9127 // Should the service remain running? Note that in the
9128 // extreme case of so many attempts to deliver a command
9129 // that it failed, that we also will stop it here.
9130 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
9131 if (sr.pendingStarts.size() == 0) {
9132 sr.startRequested = false;
9133 if (!hasClients) {
9134 // Whoops, no reason to restart!
9135 bringDownServiceLocked(sr, true);
9136 }
9137 }
9138 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009139 }
9140 }
9141
9142 if (!allowRestart) {
9143 app.services.clear();
9144 }
9145 }
9146
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009147 // Make sure we have no more records on the stopping list.
9148 int i = mStoppingServices.size();
9149 while (i > 0) {
9150 i--;
9151 ServiceRecord sr = mStoppingServices.get(i);
9152 if (sr.app == app) {
9153 mStoppingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009154 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009155 }
9156 }
9157
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009158 app.executingServices.clear();
9159 }
9160
9161 private final void removeDyingProviderLocked(ProcessRecord proc,
9162 ContentProviderRecord cpr) {
9163 synchronized (cpr) {
9164 cpr.launchingApp = null;
9165 cpr.notifyAll();
9166 }
9167
9168 mProvidersByClass.remove(cpr.info.name);
9169 String names[] = cpr.info.authority.split(";");
9170 for (int j = 0; j < names.length; j++) {
9171 mProvidersByName.remove(names[j]);
9172 }
9173
9174 Iterator<ProcessRecord> cit = cpr.clients.iterator();
9175 while (cit.hasNext()) {
9176 ProcessRecord capp = cit.next();
9177 if (!capp.persistent && capp.thread != null
9178 && capp.pid != 0
9179 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07009180 Slog.i(TAG, "Kill " + capp.processName
9181 + " (pid " + capp.pid + "): provider " + cpr.info.name
9182 + " in dying process " + proc.processName);
9183 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
9184 capp.processName, capp.setAdj, "dying provider " + proc.processName);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07009185 Process.killProcessQuiet(capp.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009186 }
9187 }
9188
9189 mLaunchingProviders.remove(cpr);
9190 }
9191
9192 /**
9193 * Main code for cleaning up a process when it has gone away. This is
9194 * called both as a result of the process dying, or directly when stopping
9195 * a process when running in single process mode.
9196 */
9197 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
9198 boolean restarting, int index) {
9199 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009200 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009201 }
9202
Dianne Hackborn36124872009-10-08 16:22:03 -07009203 mProcessesToGc.remove(app);
9204
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009205 // Dismiss any open dialogs.
9206 if (app.crashDialog != null) {
9207 app.crashDialog.dismiss();
9208 app.crashDialog = null;
9209 }
9210 if (app.anrDialog != null) {
9211 app.anrDialog.dismiss();
9212 app.anrDialog = null;
9213 }
9214 if (app.waitDialog != null) {
9215 app.waitDialog.dismiss();
9216 app.waitDialog = null;
9217 }
9218
9219 app.crashing = false;
9220 app.notResponding = false;
9221
9222 app.resetPackageList();
Dianne Hackborn1b64e0d2011-07-17 15:23:59 -07009223 app.unlinkDeathRecipient();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009224 app.thread = null;
9225 app.forcingToForeground = null;
9226 app.foregroundServices = false;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07009227 app.foregroundActivities = false;
Dianne Hackbornf0754f5b2011-07-21 16:02:07 -07009228 app.hasShownUi = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009229
9230 killServicesLocked(app, true);
9231
9232 boolean restart = false;
9233
9234 int NL = mLaunchingProviders.size();
9235
9236 // Remove published content providers.
9237 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009238 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009239 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009240 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009241 cpr.provider = null;
9242 cpr.app = null;
9243
9244 // See if someone is waiting for this provider... in which
9245 // case we don't remove it, but just let it restart.
9246 int i = 0;
9247 if (!app.bad) {
9248 for (; i<NL; i++) {
9249 if (mLaunchingProviders.get(i) == cpr) {
9250 restart = true;
9251 break;
9252 }
9253 }
9254 } else {
9255 i = NL;
9256 }
9257
9258 if (i >= NL) {
9259 removeDyingProviderLocked(app, cpr);
9260 NL = mLaunchingProviders.size();
9261 }
9262 }
9263 app.pubProviders.clear();
9264 }
9265
Dianne Hackbornf670ef72009-11-16 13:59:16 -08009266 // Take care of any launching providers waiting for this process.
9267 if (checkAppInLaunchingProvidersLocked(app, false)) {
9268 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009269 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08009270
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009271 // Unregister from connected content providers.
9272 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07009273 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009274 while (it.hasNext()) {
9275 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
9276 cpr.clients.remove(app);
9277 }
9278 app.conProviders.clear();
9279 }
9280
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009281 // At this point there may be remaining entries in mLaunchingProviders
9282 // where we were the only one waiting, so they are no longer of use.
9283 // Look for these and clean up if found.
9284 // XXX Commented out for now. Trying to figure out a way to reproduce
9285 // the actual situation to identify what is actually going on.
9286 if (false) {
9287 for (int i=0; i<NL; i++) {
9288 ContentProviderRecord cpr = (ContentProviderRecord)
9289 mLaunchingProviders.get(i);
9290 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
9291 synchronized (cpr) {
9292 cpr.launchingApp = null;
9293 cpr.notifyAll();
9294 }
9295 }
9296 }
9297 }
9298
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009299 skipCurrentReceiverLocked(app);
9300
9301 // Unregister any receivers.
9302 if (app.receivers.size() > 0) {
9303 Iterator<ReceiverList> it = app.receivers.iterator();
9304 while (it.hasNext()) {
9305 removeReceiverLocked(it.next());
9306 }
9307 app.receivers.clear();
9308 }
9309
Christopher Tate181fafa2009-05-14 11:12:14 -07009310 // If the app is undergoing backup, tell the backup manager about it
9311 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009312 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -07009313 try {
9314 IBackupManager bm = IBackupManager.Stub.asInterface(
9315 ServiceManager.getService(Context.BACKUP_SERVICE));
9316 bm.agentDisconnected(app.info.packageName);
9317 } catch (RemoteException e) {
9318 // can't happen; backup manager is local
9319 }
9320 }
9321
Jeff Sharkey287bd832011-05-28 19:36:26 -07009322 mHandler.obtainMessage(DISPATCH_PROCESS_DIED, app.pid, app.info.uid, null).sendToTarget();
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07009323
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009324 // If the caller is restarting this app, then leave it in its
9325 // current lists and let the caller take care of it.
9326 if (restarting) {
9327 return;
9328 }
9329
9330 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009331 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009332 "Removing non-persistent process during cleanup: " + app);
9333 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07009334 if (mHeavyWeightProcess == app) {
9335 mHeavyWeightProcess = null;
9336 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
9337 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009338 } else if (!app.removed) {
9339 // This app is persistent, so we need to keep its record around.
9340 // If it is not already on the pending app list, add it there
9341 // and start a new process for it.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009342 if (mPersistentStartingProcesses.indexOf(app) < 0) {
9343 mPersistentStartingProcesses.add(app);
9344 restart = true;
9345 }
9346 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07009347 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
9348 "Clean-up removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009349 mProcessesOnHold.remove(app);
9350
The Android Open Source Project4df24232009-03-05 14:34:35 -08009351 if (app == mHomeProcess) {
9352 mHomeProcess = null;
9353 }
9354
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009355 if (restart) {
9356 // We have components that still need to be running in the
9357 // process, so re-launch it.
9358 mProcessNames.put(app.processName, app.info.uid, app);
9359 startProcessLocked(app, "restart", app.processName);
9360 } else if (app.pid > 0 && app.pid != MY_PID) {
9361 // Goodbye!
9362 synchronized (mPidsSelfLocked) {
9363 mPidsSelfLocked.remove(app.pid);
9364 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
9365 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009366 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009367 }
9368 }
9369
Dianne Hackbornf670ef72009-11-16 13:59:16 -08009370 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
9371 // Look through the content providers we are waiting to have launched,
9372 // and if any run in this process then either schedule a restart of
9373 // the process or kill the client waiting for it if this process has
9374 // gone bad.
9375 int NL = mLaunchingProviders.size();
9376 boolean restart = false;
9377 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009378 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08009379 if (cpr.launchingApp == app) {
9380 if (!alwaysBad && !app.bad) {
9381 restart = true;
9382 } else {
9383 removeDyingProviderLocked(app, cpr);
9384 NL = mLaunchingProviders.size();
9385 }
9386 }
9387 }
9388 return restart;
9389 }
9390
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009391 // =========================================================
9392 // SERVICES
9393 // =========================================================
9394
9395 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
9396 ActivityManager.RunningServiceInfo info =
9397 new ActivityManager.RunningServiceInfo();
9398 info.service = r.name;
9399 if (r.app != null) {
9400 info.pid = r.app.pid;
9401 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -07009402 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009403 info.process = r.processName;
9404 info.foreground = r.isForeground;
9405 info.activeSince = r.createTime;
9406 info.started = r.startRequested;
9407 info.clientCount = r.connections.size();
9408 info.crashCount = r.crashCount;
9409 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07009410 if (r.isForeground) {
9411 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
9412 }
9413 if (r.startRequested) {
9414 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
9415 }
Dan Egnor42471dd2010-01-07 17:25:22 -08009416 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -07009417 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
9418 }
9419 if (r.app != null && r.app.persistent) {
9420 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
9421 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009422
9423 for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
9424 for (int i=0; i<connl.size(); i++) {
9425 ConnectionRecord conn = connl.get(i);
9426 if (conn.clientLabel != 0) {
9427 info.clientPackage = conn.binding.client.info.packageName;
9428 info.clientLabel = conn.clientLabel;
9429 return info;
9430 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009431 }
9432 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009433 return info;
9434 }
9435
9436 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
9437 int flags) {
9438 synchronized (this) {
9439 ArrayList<ActivityManager.RunningServiceInfo> res
9440 = new ArrayList<ActivityManager.RunningServiceInfo>();
9441
9442 if (mServices.size() > 0) {
9443 Iterator<ServiceRecord> it = mServices.values().iterator();
9444 while (it.hasNext() && res.size() < maxNum) {
9445 res.add(makeRunningServiceInfoLocked(it.next()));
9446 }
9447 }
9448
9449 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
9450 ServiceRecord r = mRestartingServices.get(i);
9451 ActivityManager.RunningServiceInfo info =
9452 makeRunningServiceInfoLocked(r);
9453 info.restarting = r.nextRestartTime;
9454 res.add(info);
9455 }
9456
9457 return res;
9458 }
9459 }
9460
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009461 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
9462 synchronized (this) {
9463 ServiceRecord r = mServices.get(name);
9464 if (r != null) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009465 for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
9466 for (int i=0; i<conn.size(); i++) {
9467 if (conn.get(i).clientIntent != null) {
9468 return conn.get(i).clientIntent;
9469 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009470 }
9471 }
9472 }
9473 }
9474 return null;
9475 }
9476
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009477 private final ServiceRecord findServiceLocked(ComponentName name,
9478 IBinder token) {
9479 ServiceRecord r = mServices.get(name);
9480 return r == token ? r : null;
9481 }
9482
9483 private final class ServiceLookupResult {
9484 final ServiceRecord record;
9485 final String permission;
9486
9487 ServiceLookupResult(ServiceRecord _record, String _permission) {
9488 record = _record;
9489 permission = _permission;
9490 }
9491 };
9492
9493 private ServiceLookupResult findServiceLocked(Intent service,
9494 String resolvedType) {
9495 ServiceRecord r = null;
9496 if (service.getComponent() != null) {
9497 r = mServices.get(service.getComponent());
9498 }
9499 if (r == null) {
9500 Intent.FilterComparison filter = new Intent.FilterComparison(service);
9501 r = mServicesByIntent.get(filter);
9502 }
9503
9504 if (r == null) {
9505 try {
9506 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009507 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009508 service, resolvedType, 0);
9509 ServiceInfo sInfo =
9510 rInfo != null ? rInfo.serviceInfo : null;
9511 if (sInfo == null) {
9512 return null;
9513 }
9514
9515 ComponentName name = new ComponentName(
9516 sInfo.applicationInfo.packageName, sInfo.name);
9517 r = mServices.get(name);
9518 } catch (RemoteException ex) {
9519 // pm is in same process, this will never happen.
9520 }
9521 }
9522 if (r != null) {
9523 int callingPid = Binder.getCallingPid();
9524 int callingUid = Binder.getCallingUid();
9525 if (checkComponentPermission(r.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009526 callingPid, callingUid, r.appInfo.uid, r.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009527 != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009528 if (!r.exported) {
9529 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
9530 + " from pid=" + callingPid
9531 + ", uid=" + callingUid
9532 + " that is not exported from uid " + r.appInfo.uid);
9533 return new ServiceLookupResult(null, "not exported from uid "
9534 + r.appInfo.uid);
9535 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009536 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009537 + " from pid=" + callingPid
9538 + ", uid=" + callingUid
9539 + " requires " + r.permission);
9540 return new ServiceLookupResult(null, r.permission);
9541 }
9542 return new ServiceLookupResult(r, null);
9543 }
9544 return null;
9545 }
9546
9547 private class ServiceRestarter implements Runnable {
9548 private ServiceRecord mService;
9549
9550 void setService(ServiceRecord service) {
9551 mService = service;
9552 }
9553
9554 public void run() {
9555 synchronized(ActivityManagerService.this) {
9556 performServiceRestartLocked(mService);
9557 }
9558 }
9559 }
9560
9561 private ServiceLookupResult retrieveServiceLocked(Intent service,
9562 String resolvedType, int callingPid, int callingUid) {
9563 ServiceRecord r = null;
9564 if (service.getComponent() != null) {
9565 r = mServices.get(service.getComponent());
9566 }
9567 Intent.FilterComparison filter = new Intent.FilterComparison(service);
9568 r = mServicesByIntent.get(filter);
9569 if (r == null) {
9570 try {
9571 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009572 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -07009573 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009574 ServiceInfo sInfo =
9575 rInfo != null ? rInfo.serviceInfo : null;
9576 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009577 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009578 ": not found");
9579 return null;
9580 }
9581
9582 ComponentName name = new ComponentName(
9583 sInfo.applicationInfo.packageName, sInfo.name);
9584 r = mServices.get(name);
9585 if (r == null) {
9586 filter = new Intent.FilterComparison(service.cloneFilter());
9587 ServiceRestarter res = new ServiceRestarter();
9588 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
9589 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
9590 synchronized (stats) {
9591 ss = stats.getServiceStatsLocked(
9592 sInfo.applicationInfo.uid, sInfo.packageName,
9593 sInfo.name);
9594 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -08009595 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009596 res.setService(r);
9597 mServices.put(name, r);
9598 mServicesByIntent.put(filter, r);
9599
9600 // Make sure this component isn't in the pending list.
9601 int N = mPendingServices.size();
9602 for (int i=0; i<N; i++) {
9603 ServiceRecord pr = mPendingServices.get(i);
9604 if (pr.name.equals(name)) {
9605 mPendingServices.remove(i);
9606 i--;
9607 N--;
9608 }
9609 }
9610 }
9611 } catch (RemoteException ex) {
9612 // pm is in same process, this will never happen.
9613 }
9614 }
9615 if (r != null) {
9616 if (checkComponentPermission(r.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009617 callingPid, callingUid, r.appInfo.uid, r.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009618 != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009619 if (!r.exported) {
9620 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
9621 + " from pid=" + callingPid
9622 + ", uid=" + callingUid
9623 + " that is not exported from uid " + r.appInfo.uid);
9624 return new ServiceLookupResult(null, "not exported from uid "
9625 + r.appInfo.uid);
9626 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009627 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009628 + " from pid=" + callingPid
9629 + ", uid=" + callingUid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009630 + " requires " + r.permission);
9631 return new ServiceLookupResult(null, r.permission);
9632 }
9633 return new ServiceLookupResult(r, null);
9634 }
9635 return null;
9636 }
9637
Dianne Hackborn287952c2010-09-22 22:34:31 -07009638 private final void bumpServiceExecutingLocked(ServiceRecord r, String why) {
9639 if (DEBUG_SERVICE) Log.v(TAG, ">>> EXECUTING "
9640 + why + " of " + r + " in app " + r.app);
9641 else if (DEBUG_SERVICE_EXECUTING) Log.v(TAG, ">>> EXECUTING "
9642 + why + " of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009643 long now = SystemClock.uptimeMillis();
9644 if (r.executeNesting == 0 && r.app != null) {
9645 if (r.app.executingServices.size() == 0) {
9646 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
9647 msg.obj = r.app;
9648 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
9649 }
9650 r.app.executingServices.add(r);
9651 }
9652 r.executeNesting++;
9653 r.executingStart = now;
9654 }
9655
9656 private final void sendServiceArgsLocked(ServiceRecord r,
9657 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009658 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009659 if (N == 0) {
9660 return;
9661 }
9662
Dianne Hackborn39792d22010-08-19 18:01:52 -07009663 while (r.pendingStarts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009664 try {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009665 ServiceRecord.StartItem si = r.pendingStarts.remove(0);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009666 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
9667 + r + " " + r.intent + " args=" + si.intent);
Dianne Hackborn3a28f222011-03-01 12:25:54 -08009668 if (si.intent == null && N > 1) {
9669 // If somehow we got a dummy null intent in the middle,
9670 // then skip it. DO NOT skip a null intent when it is
9671 // the only one in the list -- this is to support the
9672 // onStartCommand(null) case.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009673 continue;
9674 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009675 si.deliveredTime = SystemClock.uptimeMillis();
9676 r.deliveredStarts.add(si);
9677 si.deliveryCount++;
Dianne Hackborn3a28f222011-03-01 12:25:54 -08009678 if (si.targetPermissionUid >= 0 && si.intent != null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009679 grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
Dianne Hackborn7e269642010-08-25 19:50:20 -07009680 r.packageName, si.intent, si.getUriPermissionsLocked());
Dianne Hackborn39792d22010-08-19 18:01:52 -07009681 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07009682 bumpServiceExecutingLocked(r, "start");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009683 if (!oomAdjusted) {
9684 oomAdjusted = true;
9685 updateOomAdjLocked(r.app);
9686 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009687 int flags = 0;
9688 if (si.deliveryCount > 0) {
9689 flags |= Service.START_FLAG_RETRY;
9690 }
9691 if (si.doneExecutingCount > 0) {
9692 flags |= Service.START_FLAG_REDELIVERY;
9693 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07009694 r.app.thread.scheduleServiceArgs(r, si.taskRemoved, si.id, flags, si.intent);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009695 } catch (RemoteException e) {
9696 // Remote process gone... we'll let the normal cleanup take
9697 // care of this.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009698 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009699 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009700 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009701 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009702 break;
9703 }
9704 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009705 }
9706
9707 private final boolean requestServiceBindingLocked(ServiceRecord r,
9708 IntentBindRecord i, boolean rebind) {
9709 if (r.app == null || r.app.thread == null) {
9710 // If service is not currently running, can't yet bind.
9711 return false;
9712 }
9713 if ((!i.requested || rebind) && i.apps.size() > 0) {
9714 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009715 bumpServiceExecutingLocked(r, "bind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009716 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
9717 if (!rebind) {
9718 i.requested = true;
9719 }
9720 i.hasBound = true;
9721 i.doRebind = false;
9722 } catch (RemoteException e) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009723 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009724 return false;
9725 }
9726 }
9727 return true;
9728 }
9729
9730 private final void requestServiceBindingsLocked(ServiceRecord r) {
9731 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
9732 while (bindings.hasNext()) {
9733 IntentBindRecord i = bindings.next();
9734 if (!requestServiceBindingLocked(r, i, false)) {
9735 break;
9736 }
9737 }
9738 }
9739
9740 private final void realStartServiceLocked(ServiceRecord r,
9741 ProcessRecord app) throws RemoteException {
9742 if (app.thread == null) {
9743 throw new RemoteException();
9744 }
9745
9746 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -07009747 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009748
9749 app.services.add(r);
Dianne Hackborn287952c2010-09-22 22:34:31 -07009750 bumpServiceExecutingLocked(r, "create");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009751 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009752
9753 boolean created = false;
9754 try {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07009755 mStringBuilder.setLength(0);
9756 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009757 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009758 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -07009759 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009760 synchronized (r.stats.getBatteryStats()) {
9761 r.stats.startLaunchedLocked();
9762 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07009763 ensurePackageDexOpt(r.serviceInfo.packageName);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04009764 app.thread.scheduleCreateService(r, r.serviceInfo,
9765 compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo));
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009766 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009767 created = true;
9768 } finally {
9769 if (!created) {
9770 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009771 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009772 }
9773 }
9774
9775 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009776
9777 // If the service is in the started state, and there are no
9778 // pending arguments, then fake up one so its onStartCommand() will
9779 // be called.
9780 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07009781 r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
9782 null, -1));
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009783 }
9784
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009785 sendServiceArgsLocked(r, true);
9786 }
9787
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009788 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
9789 boolean allowCancel) {
9790 boolean canceled = false;
9791
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009792 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009793 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -07009794 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009795
Dianne Hackborn070783f2010-12-29 16:46:28 -08009796 if ((r.serviceInfo.applicationInfo.flags
9797 &ApplicationInfo.FLAG_PERSISTENT) != 0) {
9798 minDuration /= 4;
9799 }
9800
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009801 // Any delivered but not yet finished starts should be put back
9802 // on the pending list.
9803 final int N = r.deliveredStarts.size();
9804 if (N > 0) {
9805 for (int i=N-1; i>=0; i--) {
9806 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
Dianne Hackborn39792d22010-08-19 18:01:52 -07009807 si.removeUriPermissionsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009808 if (si.intent == null) {
9809 // We'll generate this again if needed.
9810 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
9811 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
9812 r.pendingStarts.add(0, si);
9813 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
9814 dur *= 2;
9815 if (minDuration < dur) minDuration = dur;
9816 if (resetTime < dur) resetTime = dur;
9817 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009818 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009819 + r.name);
9820 canceled = true;
9821 }
9822 }
9823 r.deliveredStarts.clear();
9824 }
9825
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009826 r.totalRestartCount++;
9827 if (r.restartDelay == 0) {
9828 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009829 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009830 } else {
9831 // If it has been a "reasonably long time" since the service
9832 // was started, then reset our restart duration back to
9833 // the beginning, so we don't infinitely increase the duration
9834 // on a service that just occasionally gets killed (which is
9835 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009836 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009837 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009838 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009839 } else {
Dianne Hackborn070783f2010-12-29 16:46:28 -08009840 if ((r.serviceInfo.applicationInfo.flags
9841 &ApplicationInfo.FLAG_PERSISTENT) != 0) {
9842 // Services in peristent processes will restart much more
9843 // quickly, since they are pretty important. (Think SystemUI).
9844 r.restartDelay += minDuration/2;
9845 } else {
9846 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
9847 if (r.restartDelay < minDuration) {
9848 r.restartDelay = minDuration;
9849 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009850 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009851 }
9852 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009853
9854 r.nextRestartTime = now + r.restartDelay;
9855
9856 // Make sure that we don't end up restarting a bunch of services
9857 // all at the same time.
9858 boolean repeat;
9859 do {
9860 repeat = false;
9861 for (int i=mRestartingServices.size()-1; i>=0; i--) {
9862 ServiceRecord r2 = mRestartingServices.get(i);
9863 if (r2 != r && r.nextRestartTime
9864 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
9865 && r.nextRestartTime
9866 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
9867 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
9868 r.restartDelay = r.nextRestartTime - now;
9869 repeat = true;
9870 break;
9871 }
9872 }
9873 } while (repeat);
9874
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009875 if (!mRestartingServices.contains(r)) {
9876 mRestartingServices.add(r);
9877 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009878
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009879 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009880
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009881 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009882 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009883 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009884 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009885 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -08009886 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009887 r.shortName, r.restartDelay);
9888
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009889 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009890 }
9891
9892 final void performServiceRestartLocked(ServiceRecord r) {
9893 if (!mRestartingServices.contains(r)) {
9894 return;
9895 }
9896 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
9897 }
9898
9899 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
9900 if (r.restartDelay == 0) {
9901 return false;
9902 }
9903 r.resetRestartCounter();
9904 mRestartingServices.remove(r);
9905 mHandler.removeCallbacks(r.restarter);
9906 return true;
9907 }
9908
9909 private final boolean bringUpServiceLocked(ServiceRecord r,
9910 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009911 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009912 //r.dump(" ");
9913
Dianne Hackborn36124872009-10-08 16:22:03 -07009914 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009915 sendServiceArgsLocked(r, false);
9916 return true;
9917 }
9918
9919 if (!whileRestarting && r.restartDelay > 0) {
9920 // If waiting for a restart, then do nothing.
9921 return true;
9922 }
9923
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009924 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009925
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009926 // We are now bringing the service up, so no longer in the
9927 // restarting state.
9928 mRestartingServices.remove(r);
9929
Dianne Hackborne7f97212011-02-24 14:40:20 -08009930 // Service is now being launched, its package can't be stopped.
9931 try {
9932 AppGlobals.getPackageManager().setPackageStoppedState(
9933 r.packageName, false);
9934 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08009935 } catch (IllegalArgumentException e) {
9936 Slog.w(TAG, "Failed trying to unstop package "
9937 + r.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08009938 }
9939
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009940 final String appName = r.processName;
9941 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
9942 if (app != null && app.thread != null) {
9943 try {
Dianne Hackborn6c418d52011-06-29 14:05:33 -07009944 app.addPackage(r.appInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009945 realStartServiceLocked(r, app);
9946 return true;
9947 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009948 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009949 }
9950
9951 // If a dead object exception was thrown -- fall through to
9952 // restart the application.
9953 }
9954
Dianne Hackborn36124872009-10-08 16:22:03 -07009955 // Not running -- get it started, and enqueue this service record
9956 // to be executed when the app comes up.
9957 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
9958 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009959 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -07009960 + r.appInfo.packageName + "/"
9961 + r.appInfo.uid + " for service "
9962 + r.intent.getIntent() + ": process is bad");
9963 bringDownServiceLocked(r, true);
9964 return false;
9965 }
9966
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009967 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009968 mPendingServices.add(r);
9969 }
Dianne Hackborn36124872009-10-08 16:22:03 -07009970
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009971 return true;
9972 }
9973
9974 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009975 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009976 //r.dump(" ");
9977
9978 // Does it still need to run?
9979 if (!force && r.startRequested) {
9980 return;
9981 }
9982 if (r.connections.size() > 0) {
9983 if (!force) {
9984 // XXX should probably keep a count of the number of auto-create
9985 // connections directly in the service.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009986 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009987 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009988 ArrayList<ConnectionRecord> cr = it.next();
9989 for (int i=0; i<cr.size(); i++) {
9990 if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
9991 return;
9992 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009993 }
9994 }
9995 }
9996
9997 // Report to all of the connections that the service is no longer
9998 // available.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009999 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010000 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010001 ArrayList<ConnectionRecord> c = it.next();
10002 for (int i=0; i<c.size(); i++) {
10003 try {
10004 c.get(i).conn.connected(r.name, null);
10005 } catch (Exception e) {
10006 Slog.w(TAG, "Failure disconnecting service " + r.name +
10007 " to connection " + c.get(i).conn.asBinder() +
10008 " (in " + c.get(i).binding.client.processName + ")", e);
10009 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010010 }
10011 }
10012 }
10013
10014 // Tell the service that it has been unbound.
10015 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
10016 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
10017 while (it.hasNext()) {
10018 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010019 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010020 + ": hasBound=" + ibr.hasBound);
10021 if (r.app != null && r.app.thread != null && ibr.hasBound) {
10022 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010023 bumpServiceExecutingLocked(r, "bring down unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010024 updateOomAdjLocked(r.app);
10025 ibr.hasBound = false;
10026 r.app.thread.scheduleUnbindService(r,
10027 ibr.intent.getIntent());
10028 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010029 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010030 + r.shortName, e);
10031 serviceDoneExecutingLocked(r, true);
10032 }
10033 }
10034 }
10035 }
10036
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010037 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010038 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010039 System.identityHashCode(r), r.shortName,
10040 (r.app != null) ? r.app.pid : -1);
10041
10042 mServices.remove(r.name);
10043 mServicesByIntent.remove(r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010044 r.totalRestartCount = 0;
10045 unscheduleServiceRestartLocked(r);
10046
10047 // Also make sure it is not on the pending list.
10048 int N = mPendingServices.size();
10049 for (int i=0; i<N; i++) {
10050 if (mPendingServices.get(i) == r) {
10051 mPendingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010052 if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010053 i--;
10054 N--;
10055 }
10056 }
10057
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010058 r.cancelNotification();
10059 r.isForeground = false;
10060 r.foregroundId = 0;
10061 r.foregroundNoti = null;
10062
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010063 // Clear start entries.
Dianne Hackborn39792d22010-08-19 18:01:52 -070010064 r.clearDeliveredStartsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010065 r.pendingStarts.clear();
10066
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010067 if (r.app != null) {
10068 synchronized (r.stats.getBatteryStats()) {
10069 r.stats.stopLaunchedLocked();
10070 }
10071 r.app.services.remove(r);
10072 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010073 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010074 bumpServiceExecutingLocked(r, "stop");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010075 mStoppingServices.add(r);
10076 updateOomAdjLocked(r.app);
10077 r.app.thread.scheduleStopService(r);
10078 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010079 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010080 + r.shortName, e);
10081 serviceDoneExecutingLocked(r, true);
10082 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010083 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010084 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010085 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010086 TAG, "Removed service that has no process: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010087 }
10088 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010089 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010090 TAG, "Removed service that is not running: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010091 }
Vairavan Srinivasana207ce22010-12-23 13:51:48 -080010092
10093 if (r.bindings.size() > 0) {
10094 r.bindings.clear();
10095 }
10096
10097 if (r.restarter instanceof ServiceRestarter) {
10098 ((ServiceRestarter)r.restarter).setService(null);
10099 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010100 }
10101
10102 ComponentName startServiceLocked(IApplicationThread caller,
10103 Intent service, String resolvedType,
10104 int callingPid, int callingUid) {
10105 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010106 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010107 + " type=" + resolvedType + " args=" + service.getExtras());
10108
10109 if (caller != null) {
10110 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10111 if (callerApp == null) {
10112 throw new SecurityException(
10113 "Unable to find app for caller " + caller
10114 + " (pid=" + Binder.getCallingPid()
10115 + ") when starting service " + service);
10116 }
10117 }
10118
10119 ServiceLookupResult res =
10120 retrieveServiceLocked(service, resolvedType,
10121 callingPid, callingUid);
10122 if (res == null) {
10123 return null;
10124 }
10125 if (res.record == null) {
10126 return new ComponentName("!", res.permission != null
10127 ? res.permission : "private to package");
10128 }
10129 ServiceRecord r = res.record;
Dianne Hackborn39792d22010-08-19 18:01:52 -070010130 int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
10131 callingUid, r.packageName, service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010132 if (unscheduleServiceRestartLocked(r)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010133 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010134 }
10135 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010136 r.callStart = false;
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010137 r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
Dianne Hackborn39792d22010-08-19 18:01:52 -070010138 service, targetPermissionUid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010139 r.lastActivity = SystemClock.uptimeMillis();
10140 synchronized (r.stats.getBatteryStats()) {
10141 r.stats.startRunningLocked();
10142 }
10143 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
10144 return new ComponentName("!", "Service process is bad");
10145 }
10146 return r.name;
10147 }
10148 }
10149
10150 public ComponentName startService(IApplicationThread caller, Intent service,
10151 String resolvedType) {
10152 // Refuse possible leaked file descriptors
10153 if (service != null && service.hasFileDescriptors() == true) {
10154 throw new IllegalArgumentException("File descriptors passed in Intent");
10155 }
10156
10157 synchronized(this) {
10158 final int callingPid = Binder.getCallingPid();
10159 final int callingUid = Binder.getCallingUid();
10160 final long origId = Binder.clearCallingIdentity();
10161 ComponentName res = startServiceLocked(caller, service,
10162 resolvedType, callingPid, callingUid);
10163 Binder.restoreCallingIdentity(origId);
10164 return res;
10165 }
10166 }
10167
10168 ComponentName startServiceInPackage(int uid,
10169 Intent service, String resolvedType) {
10170 synchronized(this) {
10171 final long origId = Binder.clearCallingIdentity();
10172 ComponentName res = startServiceLocked(null, service,
10173 resolvedType, -1, uid);
10174 Binder.restoreCallingIdentity(origId);
10175 return res;
10176 }
10177 }
10178
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010179 private void stopServiceLocked(ServiceRecord service) {
10180 synchronized (service.stats.getBatteryStats()) {
10181 service.stats.stopRunningLocked();
10182 }
10183 service.startRequested = false;
10184 service.callStart = false;
10185 bringDownServiceLocked(service, false);
10186 }
10187
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010188 public int stopService(IApplicationThread caller, Intent service,
10189 String resolvedType) {
10190 // Refuse possible leaked file descriptors
10191 if (service != null && service.hasFileDescriptors() == true) {
10192 throw new IllegalArgumentException("File descriptors passed in Intent");
10193 }
10194
10195 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010196 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010197 + " type=" + resolvedType);
10198
10199 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10200 if (caller != null && callerApp == null) {
10201 throw new SecurityException(
10202 "Unable to find app for caller " + caller
10203 + " (pid=" + Binder.getCallingPid()
10204 + ") when stopping service " + service);
10205 }
10206
10207 // If this service is active, make sure it is stopped.
10208 ServiceLookupResult r = findServiceLocked(service, resolvedType);
10209 if (r != null) {
10210 if (r.record != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010211 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010212 try {
10213 stopServiceLocked(r.record);
10214 } finally {
10215 Binder.restoreCallingIdentity(origId);
10216 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010217 return 1;
10218 }
10219 return -1;
10220 }
10221 }
10222
10223 return 0;
10224 }
10225
10226 public IBinder peekService(Intent service, String resolvedType) {
10227 // Refuse possible leaked file descriptors
10228 if (service != null && service.hasFileDescriptors() == true) {
10229 throw new IllegalArgumentException("File descriptors passed in Intent");
10230 }
10231
10232 IBinder ret = null;
10233
10234 synchronized(this) {
10235 ServiceLookupResult r = findServiceLocked(service, resolvedType);
10236
10237 if (r != null) {
10238 // r.record is null if findServiceLocked() failed the caller permission check
10239 if (r.record == null) {
10240 throw new SecurityException(
10241 "Permission Denial: Accessing service " + r.record.name
10242 + " from pid=" + Binder.getCallingPid()
10243 + ", uid=" + Binder.getCallingUid()
10244 + " requires " + r.permission);
10245 }
10246 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
10247 if (ib != null) {
10248 ret = ib.binder;
10249 }
10250 }
10251 }
10252
10253 return ret;
10254 }
10255
10256 public boolean stopServiceToken(ComponentName className, IBinder token,
10257 int startId) {
10258 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010259 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010260 + " " + token + " startId=" + startId);
10261 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010262 if (r != null) {
10263 if (startId >= 0) {
10264 // Asked to only stop if done with all work. Note that
10265 // to avoid leaks, we will take this as dropping all
10266 // start items up to and including this one.
10267 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
10268 if (si != null) {
10269 while (r.deliveredStarts.size() > 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -070010270 ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
10271 cur.removeUriPermissionsLocked();
10272 if (cur == si) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010273 break;
10274 }
10275 }
10276 }
10277
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010278 if (r.getLastStartId() != startId) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010279 return false;
10280 }
10281
10282 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010283 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010284 + " is last, but have " + r.deliveredStarts.size()
10285 + " remaining args");
10286 }
10287 }
10288
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010289 synchronized (r.stats.getBatteryStats()) {
10290 r.stats.stopRunningLocked();
10291 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010292 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010293 }
10294 final long origId = Binder.clearCallingIdentity();
10295 bringDownServiceLocked(r, false);
10296 Binder.restoreCallingIdentity(origId);
10297 return true;
10298 }
10299 }
10300 return false;
10301 }
10302
10303 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010304 int id, Notification notification, boolean removeNotification) {
10305 final long origId = Binder.clearCallingIdentity();
10306 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010307 synchronized(this) {
10308 ServiceRecord r = findServiceLocked(className, token);
10309 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010310 if (id != 0) {
10311 if (notification == null) {
10312 throw new IllegalArgumentException("null notification");
10313 }
10314 if (r.foregroundId != id) {
10315 r.cancelNotification();
10316 r.foregroundId = id;
10317 }
10318 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
10319 r.foregroundNoti = notification;
10320 r.isForeground = true;
10321 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010322 if (r.app != null) {
10323 updateServiceForegroundLocked(r.app, true);
10324 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010325 } else {
10326 if (r.isForeground) {
10327 r.isForeground = false;
10328 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -070010329 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010330 updateServiceForegroundLocked(r.app, true);
10331 }
10332 }
10333 if (removeNotification) {
10334 r.cancelNotification();
10335 r.foregroundId = 0;
10336 r.foregroundNoti = null;
10337 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010338 }
10339 }
10340 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010341 } finally {
10342 Binder.restoreCallingIdentity(origId);
10343 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010344 }
10345
10346 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
10347 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -070010348 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010349 if (sr.isForeground) {
10350 anyForeground = true;
10351 break;
10352 }
10353 }
10354 if (anyForeground != proc.foregroundServices) {
10355 proc.foregroundServices = anyForeground;
10356 if (oomAdj) {
10357 updateOomAdjLocked();
10358 }
10359 }
10360 }
10361
10362 public int bindService(IApplicationThread caller, IBinder token,
10363 Intent service, String resolvedType,
10364 IServiceConnection connection, int flags) {
10365 // Refuse possible leaked file descriptors
10366 if (service != null && service.hasFileDescriptors() == true) {
10367 throw new IllegalArgumentException("File descriptors passed in Intent");
10368 }
10369
10370 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010371 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010372 + " type=" + resolvedType + " conn=" + connection.asBinder()
10373 + " flags=0x" + Integer.toHexString(flags));
10374 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10375 if (callerApp == null) {
10376 throw new SecurityException(
10377 "Unable to find app for caller " + caller
10378 + " (pid=" + Binder.getCallingPid()
10379 + ") when binding service " + service);
10380 }
10381
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010382 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010383 if (token != null) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -070010384 activity = mMainStack.isInStackLocked(token);
10385 if (activity == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010386 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010387 return 0;
10388 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010389 }
10390
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010391 int clientLabel = 0;
10392 PendingIntent clientIntent = null;
10393
10394 if (callerApp.info.uid == Process.SYSTEM_UID) {
10395 // Hacky kind of thing -- allow system stuff to tell us
10396 // what they are, so we can report this elsewhere for
10397 // others to know why certain services are running.
10398 try {
10399 clientIntent = (PendingIntent)service.getParcelableExtra(
10400 Intent.EXTRA_CLIENT_INTENT);
10401 } catch (RuntimeException e) {
10402 }
10403 if (clientIntent != null) {
10404 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
10405 if (clientLabel != 0) {
10406 // There are no useful extras in the intent, trash them.
10407 // System code calling with this stuff just needs to know
10408 // this will happen.
10409 service = service.cloneFilter();
10410 }
10411 }
10412 }
10413
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010414 ServiceLookupResult res =
10415 retrieveServiceLocked(service, resolvedType,
10416 Binder.getCallingPid(), Binder.getCallingUid());
10417 if (res == null) {
10418 return 0;
10419 }
10420 if (res.record == null) {
10421 return -1;
10422 }
10423 ServiceRecord s = res.record;
10424
10425 final long origId = Binder.clearCallingIdentity();
10426
10427 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010428 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010429 + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010430 }
10431
10432 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
10433 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010434 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010435
10436 IBinder binder = connection.asBinder();
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010437 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
10438 if (clist == null) {
10439 clist = new ArrayList<ConnectionRecord>();
10440 s.connections.put(binder, clist);
10441 }
10442 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010443 b.connections.add(c);
10444 if (activity != null) {
10445 if (activity.connections == null) {
10446 activity.connections = new HashSet<ConnectionRecord>();
10447 }
10448 activity.connections.add(c);
10449 }
10450 b.client.connections.add(c);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010451 clist = mServiceConnections.get(binder);
10452 if (clist == null) {
10453 clist = new ArrayList<ConnectionRecord>();
10454 mServiceConnections.put(binder, clist);
10455 }
10456 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010457
10458 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
10459 s.lastActivity = SystemClock.uptimeMillis();
10460 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
10461 return 0;
10462 }
10463 }
10464
10465 if (s.app != null) {
10466 // This could have made the service more important.
10467 updateOomAdjLocked(s.app);
10468 }
10469
Joe Onorato8a9b2202010-02-26 18:56:32 -080010470 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010471 + ": received=" + b.intent.received
10472 + " apps=" + b.intent.apps.size()
10473 + " doRebind=" + b.intent.doRebind);
10474
10475 if (s.app != null && b.intent.received) {
10476 // Service is already running, so we can immediately
10477 // publish the connection.
10478 try {
10479 c.conn.connected(s.name, b.intent.binder);
10480 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010481 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010482 + " to connection " + c.conn.asBinder()
10483 + " (in " + c.binding.client.processName + ")", e);
10484 }
10485
10486 // If this is the first app connected back to this binding,
10487 // and the service had previously asked to be told when
10488 // rebound, then do so.
10489 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
10490 requestServiceBindingLocked(s, b.intent, true);
10491 }
10492 } else if (!b.intent.requested) {
10493 requestServiceBindingLocked(s, b.intent, false);
10494 }
10495
10496 Binder.restoreCallingIdentity(origId);
10497 }
10498
10499 return 1;
10500 }
10501
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010502 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010503 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010504 IBinder binder = c.conn.asBinder();
10505 AppBindRecord b = c.binding;
10506 ServiceRecord s = b.service;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010507 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
10508 if (clist != null) {
10509 clist.remove(c);
10510 if (clist.size() == 0) {
10511 s.connections.remove(binder);
10512 }
10513 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010514 b.connections.remove(c);
10515 if (c.activity != null && c.activity != skipAct) {
10516 if (c.activity.connections != null) {
10517 c.activity.connections.remove(c);
10518 }
10519 }
10520 if (b.client != skipApp) {
10521 b.client.connections.remove(c);
10522 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010523 clist = mServiceConnections.get(binder);
10524 if (clist != null) {
10525 clist.remove(c);
10526 if (clist.size() == 0) {
10527 mServiceConnections.remove(binder);
10528 }
10529 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010530
10531 if (b.connections.size() == 0) {
10532 b.intent.apps.remove(b.client);
10533 }
10534
Joe Onorato8a9b2202010-02-26 18:56:32 -080010535 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010536 + ": shouldUnbind=" + b.intent.hasBound);
10537 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
10538 && b.intent.hasBound) {
10539 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010540 bumpServiceExecutingLocked(s, "unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010541 updateOomAdjLocked(s.app);
10542 b.intent.hasBound = false;
10543 // Assume the client doesn't want to know about a rebind;
10544 // we will deal with that later if it asks for one.
10545 b.intent.doRebind = false;
10546 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
10547 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010548 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010549 serviceDoneExecutingLocked(s, true);
10550 }
10551 }
10552
10553 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
10554 bringDownServiceLocked(s, false);
10555 }
10556 }
10557
10558 public boolean unbindService(IServiceConnection connection) {
10559 synchronized (this) {
10560 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010561 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010562 ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
10563 if (clist == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010564 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010565 + connection.asBinder());
10566 return false;
10567 }
10568
10569 final long origId = Binder.clearCallingIdentity();
10570
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010571 while (clist.size() > 0) {
10572 ConnectionRecord r = clist.get(0);
10573 removeConnectionLocked(r, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010574
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010575 if (r.binding.service.app != null) {
10576 // This could have made the service less important.
10577 updateOomAdjLocked(r.binding.service.app);
10578 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010579 }
10580
10581 Binder.restoreCallingIdentity(origId);
10582 }
10583
10584 return true;
10585 }
10586
10587 public void publishService(IBinder token, Intent intent, IBinder service) {
10588 // Refuse possible leaked file descriptors
10589 if (intent != null && intent.hasFileDescriptors() == true) {
10590 throw new IllegalArgumentException("File descriptors passed in Intent");
10591 }
10592
10593 synchronized(this) {
10594 if (!(token instanceof ServiceRecord)) {
10595 throw new IllegalArgumentException("Invalid service token");
10596 }
10597 ServiceRecord r = (ServiceRecord)token;
10598
10599 final long origId = Binder.clearCallingIdentity();
10600
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010601 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010602 + " " + intent + ": " + service);
10603 if (r != null) {
10604 Intent.FilterComparison filter
10605 = new Intent.FilterComparison(intent);
10606 IntentBindRecord b = r.bindings.get(filter);
10607 if (b != null && !b.received) {
10608 b.binder = service;
10609 b.requested = true;
10610 b.received = true;
10611 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010612 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010613 = r.connections.values().iterator();
10614 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010615 ArrayList<ConnectionRecord> clist = it.next();
10616 for (int i=0; i<clist.size(); i++) {
10617 ConnectionRecord c = clist.get(i);
10618 if (!filter.equals(c.binding.intent.intent)) {
10619 if (DEBUG_SERVICE) Slog.v(
10620 TAG, "Not publishing to: " + c);
10621 if (DEBUG_SERVICE) Slog.v(
10622 TAG, "Bound intent: " + c.binding.intent.intent);
10623 if (DEBUG_SERVICE) Slog.v(
10624 TAG, "Published intent: " + intent);
10625 continue;
10626 }
10627 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
10628 try {
10629 c.conn.connected(r.name, service);
10630 } catch (Exception e) {
10631 Slog.w(TAG, "Failure sending service " + r.name +
10632 " to connection " + c.conn.asBinder() +
10633 " (in " + c.binding.client.processName + ")", e);
10634 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010635 }
10636 }
10637 }
10638 }
10639
10640 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
10641
10642 Binder.restoreCallingIdentity(origId);
10643 }
10644 }
10645 }
10646
10647 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
10648 // Refuse possible leaked file descriptors
10649 if (intent != null && intent.hasFileDescriptors() == true) {
10650 throw new IllegalArgumentException("File descriptors passed in Intent");
10651 }
10652
10653 synchronized(this) {
10654 if (!(token instanceof ServiceRecord)) {
10655 throw new IllegalArgumentException("Invalid service token");
10656 }
10657 ServiceRecord r = (ServiceRecord)token;
10658
10659 final long origId = Binder.clearCallingIdentity();
10660
10661 if (r != null) {
10662 Intent.FilterComparison filter
10663 = new Intent.FilterComparison(intent);
10664 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010665 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010666 + " at " + b + ": apps="
10667 + (b != null ? b.apps.size() : 0));
10668 if (b != null) {
10669 if (b.apps.size() > 0) {
10670 // Applications have already bound since the last
10671 // unbind, so just rebind right here.
10672 requestServiceBindingLocked(r, b, true);
10673 } else {
10674 // Note to tell the service the next time there is
10675 // a new client.
10676 b.doRebind = true;
10677 }
10678 }
10679
10680 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
10681
10682 Binder.restoreCallingIdentity(origId);
10683 }
10684 }
10685 }
10686
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010687 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010688 synchronized(this) {
10689 if (!(token instanceof ServiceRecord)) {
10690 throw new IllegalArgumentException("Invalid service token");
10691 }
10692 ServiceRecord r = (ServiceRecord)token;
10693 boolean inStopping = mStoppingServices.contains(token);
10694 if (r != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010695 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010696 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010697 + " with incorrect token: given " + token
10698 + ", expected " + r);
10699 return;
10700 }
10701
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010702 if (type == 1) {
10703 // This is a call from a service start... take care of
10704 // book-keeping.
10705 r.callStart = true;
10706 switch (res) {
10707 case Service.START_STICKY_COMPATIBILITY:
10708 case Service.START_STICKY: {
10709 // We are done with the associated start arguments.
10710 r.findDeliveredStart(startId, true);
10711 // Don't stop if killed.
10712 r.stopIfKilled = false;
10713 break;
10714 }
10715 case Service.START_NOT_STICKY: {
10716 // We are done with the associated start arguments.
10717 r.findDeliveredStart(startId, true);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010718 if (r.getLastStartId() == startId) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010719 // There is no more work, and this service
10720 // doesn't want to hang around if killed.
10721 r.stopIfKilled = true;
10722 }
10723 break;
10724 }
10725 case Service.START_REDELIVER_INTENT: {
10726 // We'll keep this item until they explicitly
10727 // call stop for it, but keep track of the fact
10728 // that it was delivered.
10729 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
10730 if (si != null) {
10731 si.deliveryCount = 0;
10732 si.doneExecutingCount++;
10733 // Don't stop if killed.
10734 r.stopIfKilled = true;
10735 }
10736 break;
10737 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010738 case Service.START_TASK_REMOVED_COMPLETE: {
10739 // Special processing for onTaskRemoved(). Don't
10740 // impact normal onStartCommand() processing.
10741 r.findDeliveredStart(startId, true);
10742 break;
10743 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010744 default:
10745 throw new IllegalArgumentException(
10746 "Unknown service start result: " + res);
10747 }
10748 if (res == Service.START_STICKY_COMPATIBILITY) {
10749 r.callStart = false;
10750 }
10751 }
10752
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010753 final long origId = Binder.clearCallingIdentity();
10754 serviceDoneExecutingLocked(r, inStopping);
10755 Binder.restoreCallingIdentity(origId);
10756 } else {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010757 Slog.w(TAG, "Done executing unknown service from pid "
10758 + Binder.getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010759 }
10760 }
10761 }
10762
10763 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010764 if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
10765 + ": nesting=" + r.executeNesting
10766 + ", inStopping=" + inStopping + ", app=" + r.app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070010767 else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010768 r.executeNesting--;
10769 if (r.executeNesting <= 0 && r.app != null) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010770 if (DEBUG_SERVICE) Slog.v(TAG,
10771 "Nesting at 0 of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010772 r.app.executingServices.remove(r);
10773 if (r.app.executingServices.size() == 0) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010774 if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,
10775 "No more executingServices of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010776 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
10777 }
10778 if (inStopping) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010779 if (DEBUG_SERVICE) Slog.v(TAG,
10780 "doneExecuting remove stopping " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010781 mStoppingServices.remove(r);
Mattias Petersson3996b412010-10-27 09:32:51 +020010782 r.bindings.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010783 }
10784 updateOomAdjLocked(r.app);
10785 }
10786 }
10787
10788 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010789 String anrMessage = null;
10790
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010791 synchronized(this) {
10792 if (proc.executingServices.size() == 0 || proc.thread == null) {
10793 return;
10794 }
10795 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
10796 Iterator<ServiceRecord> it = proc.executingServices.iterator();
10797 ServiceRecord timeout = null;
10798 long nextTime = 0;
10799 while (it.hasNext()) {
10800 ServiceRecord sr = it.next();
10801 if (sr.executingStart < maxTime) {
10802 timeout = sr;
10803 break;
10804 }
10805 if (sr.executingStart > nextTime) {
10806 nextTime = sr.executingStart;
10807 }
10808 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010809 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010810 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010811 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010812 } else {
10813 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
10814 msg.obj = proc;
10815 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
10816 }
10817 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010818
10819 if (anrMessage != null) {
10820 appNotResponding(proc, null, null, anrMessage);
10821 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010822 }
10823
10824 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070010825 // BACKUP AND RESTORE
10826 // =========================================================
10827
10828 // Cause the target app to be launched if necessary and its backup agent
10829 // instantiated. The backup agent will invoke backupAgentCreated() on the
10830 // activity manager to announce its creation.
10831 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010832 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070010833 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
10834
10835 synchronized(this) {
10836 // !!! TODO: currently no check here that we're already bound
10837 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
10838 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
10839 synchronized (stats) {
10840 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
10841 }
10842
Dianne Hackborne7f97212011-02-24 14:40:20 -080010843 // Backup agent is now in use, its package can't be stopped.
10844 try {
10845 AppGlobals.getPackageManager().setPackageStoppedState(
10846 app.packageName, false);
10847 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -080010848 } catch (IllegalArgumentException e) {
10849 Slog.w(TAG, "Failed trying to unstop package "
10850 + app.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -080010851 }
10852
Christopher Tate181fafa2009-05-14 11:12:14 -070010853 BackupRecord r = new BackupRecord(ss, app, backupMode);
Christopher Tate4a627c72011-04-01 14:43:32 -070010854 ComponentName hostingName = (backupMode == IApplicationThread.BACKUP_MODE_INCREMENTAL)
10855 ? new ComponentName(app.packageName, app.backupAgentName)
10856 : new ComponentName("android", "FullBackupAgent");
Christopher Tate181fafa2009-05-14 11:12:14 -070010857 // startProcessLocked() returns existing proc's record if it's already running
10858 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010859 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070010860 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010861 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070010862 return false;
10863 }
10864
10865 r.app = proc;
10866 mBackupTarget = r;
10867 mBackupAppName = app.packageName;
10868
Christopher Tate6fa95972009-06-05 18:43:55 -070010869 // Try not to kill the process during backup
10870 updateOomAdjLocked(proc);
10871
Christopher Tate181fafa2009-05-14 11:12:14 -070010872 // If the process is already attached, schedule the creation of the backup agent now.
10873 // If it is not yet live, this will be done when it attaches to the framework.
10874 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010875 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070010876 try {
Dianne Hackborne2515ee2011-04-27 18:52:56 -040010877 proc.thread.scheduleCreateBackupAgent(app,
10878 compatibilityInfoForPackageLocked(app), backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070010879 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070010880 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070010881 }
10882 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010883 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070010884 }
10885 // Invariants: at this point, the target app process exists and the application
10886 // is either already running or in the process of coming up. mBackupTarget and
10887 // mBackupAppName describe the app, so that when it binds back to the AM we
10888 // know that it's scheduled for a backup-agent operation.
10889 }
10890
10891 return true;
10892 }
10893
10894 // A backup agent has just come up
10895 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010896 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070010897 + " = " + agent);
10898
10899 synchronized(this) {
10900 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010901 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070010902 return;
10903 }
Dianne Hackborn06740692010-09-22 22:46:21 -070010904 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010905
Dianne Hackborn06740692010-09-22 22:46:21 -070010906 long oldIdent = Binder.clearCallingIdentity();
10907 try {
10908 IBackupManager bm = IBackupManager.Stub.asInterface(
10909 ServiceManager.getService(Context.BACKUP_SERVICE));
10910 bm.agentConnected(agentPackageName, agent);
10911 } catch (RemoteException e) {
10912 // can't happen; the backup manager service is local
10913 } catch (Exception e) {
10914 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
10915 e.printStackTrace();
10916 } finally {
10917 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070010918 }
10919 }
10920
10921 // done with this agent
10922 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010923 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070010924 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010925 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070010926 return;
10927 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010928
10929 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070010930 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010931 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070010932 return;
10933 }
10934
Christopher Tate181fafa2009-05-14 11:12:14 -070010935 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010936 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070010937 return;
10938 }
10939
Christopher Tate6fa95972009-06-05 18:43:55 -070010940 ProcessRecord proc = mBackupTarget.app;
10941 mBackupTarget = null;
10942 mBackupAppName = null;
10943
10944 // Not backing this app up any more; reset its OOM adjustment
10945 updateOomAdjLocked(proc);
10946
Christopher Tatec7b31e32009-06-10 15:49:30 -070010947 // If the app crashed during backup, 'thread' will be null here
10948 if (proc.thread != null) {
10949 try {
Dianne Hackborne2515ee2011-04-27 18:52:56 -040010950 proc.thread.scheduleDestroyBackupAgent(appInfo,
10951 compatibilityInfoForPackageLocked(appInfo));
Christopher Tatec7b31e32009-06-10 15:49:30 -070010952 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010953 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070010954 e.printStackTrace();
10955 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010956 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010957 }
10958 }
10959 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010960 // BROADCASTS
10961 // =========================================================
10962
Josh Bartel7f208742010-02-25 11:01:44 -060010963 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010964 List cur) {
10965 final ContentResolver resolver = mContext.getContentResolver();
10966 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
10967 if (list == null) {
10968 return cur;
10969 }
10970 int N = list.size();
10971 for (int i=0; i<N; i++) {
10972 Intent intent = list.get(i);
10973 if (filter.match(resolver, intent, true, TAG) >= 0) {
10974 if (cur == null) {
10975 cur = new ArrayList<Intent>();
10976 }
10977 cur.add(intent);
10978 }
10979 }
10980 return cur;
10981 }
10982
10983 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010984 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010985 + mBroadcastsScheduled);
10986
10987 if (mBroadcastsScheduled) {
10988 return;
10989 }
10990 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
10991 mBroadcastsScheduled = true;
10992 }
10993
Dianne Hackborn6c418d52011-06-29 14:05:33 -070010994 public Intent registerReceiver(IApplicationThread caller, String callerPackage,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010995 IIntentReceiver receiver, IntentFilter filter, String permission) {
10996 synchronized(this) {
10997 ProcessRecord callerApp = null;
10998 if (caller != null) {
10999 callerApp = getRecordForAppLocked(caller);
11000 if (callerApp == null) {
11001 throw new SecurityException(
11002 "Unable to find app for caller " + caller
11003 + " (pid=" + Binder.getCallingPid()
11004 + ") when registering receiver " + receiver);
11005 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -070011006 if (callerApp.info.uid != Process.SYSTEM_UID &&
11007 !callerApp.pkgList.contains(callerPackage)) {
11008 throw new SecurityException("Given caller package " + callerPackage
11009 + " is not running in process " + callerApp);
11010 }
11011 } else {
11012 callerPackage = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011013 }
11014
11015 List allSticky = null;
11016
11017 // Look for any matching sticky broadcasts...
11018 Iterator actions = filter.actionsIterator();
11019 if (actions != null) {
11020 while (actions.hasNext()) {
11021 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -060011022 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011023 }
11024 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060011025 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011026 }
11027
11028 // The first sticky in the list is returned directly back to
11029 // the client.
11030 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
11031
Joe Onorato8a9b2202010-02-26 18:56:32 -080011032 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011033 + ": " + sticky);
11034
11035 if (receiver == null) {
11036 return sticky;
11037 }
11038
11039 ReceiverList rl
11040 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
11041 if (rl == null) {
11042 rl = new ReceiverList(this, callerApp,
11043 Binder.getCallingPid(),
11044 Binder.getCallingUid(), receiver);
11045 if (rl.app != null) {
11046 rl.app.receivers.add(rl);
11047 } else {
11048 try {
11049 receiver.asBinder().linkToDeath(rl, 0);
11050 } catch (RemoteException e) {
11051 return sticky;
11052 }
11053 rl.linkedToDeath = true;
11054 }
11055 mRegisteredReceivers.put(receiver.asBinder(), rl);
11056 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -070011057 BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage, permission);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011058 rl.add(bf);
11059 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011060 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011061 }
11062 mReceiverResolver.addFilter(bf);
11063
11064 // Enqueue broadcasts for all existing stickies that match
11065 // this filter.
11066 if (allSticky != null) {
11067 ArrayList receivers = new ArrayList();
11068 receivers.add(bf);
11069
11070 int N = allSticky.size();
11071 for (int i=0; i<N; i++) {
11072 Intent intent = (Intent)allSticky.get(i);
11073 BroadcastRecord r = new BroadcastRecord(intent, null,
11074 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011075 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011076 if (mParallelBroadcasts.size() == 0) {
11077 scheduleBroadcastsLocked();
11078 }
11079 mParallelBroadcasts.add(r);
11080 }
11081 }
11082
11083 return sticky;
11084 }
11085 }
11086
11087 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011088 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011089
11090 boolean doNext = false;
11091
11092 synchronized(this) {
11093 ReceiverList rl
11094 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
11095 if (rl != null) {
11096 if (rl.curBroadcast != null) {
11097 BroadcastRecord r = rl.curBroadcast;
11098 doNext = finishReceiverLocked(
11099 receiver.asBinder(), r.resultCode, r.resultData,
11100 r.resultExtras, r.resultAbort, true);
11101 }
11102
11103 if (rl.app != null) {
11104 rl.app.receivers.remove(rl);
11105 }
11106 removeReceiverLocked(rl);
11107 if (rl.linkedToDeath) {
11108 rl.linkedToDeath = false;
11109 rl.receiver.asBinder().unlinkToDeath(rl, 0);
11110 }
11111 }
11112 }
11113
11114 if (!doNext) {
11115 return;
11116 }
11117
11118 final long origId = Binder.clearCallingIdentity();
11119 processNextBroadcast(false);
11120 trimApplications();
11121 Binder.restoreCallingIdentity(origId);
11122 }
11123
11124 void removeReceiverLocked(ReceiverList rl) {
11125 mRegisteredReceivers.remove(rl.receiver.asBinder());
11126 int N = rl.size();
11127 for (int i=0; i<N; i++) {
11128 mReceiverResolver.removeFilter(rl.get(i));
11129 }
11130 }
11131
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070011132 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
11133 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
11134 ProcessRecord r = mLruProcesses.get(i);
11135 if (r.thread != null) {
11136 try {
11137 r.thread.dispatchPackageBroadcast(cmd, packages);
11138 } catch (RemoteException ex) {
11139 }
11140 }
11141 }
11142 }
11143
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011144 private final int broadcastIntentLocked(ProcessRecord callerApp,
11145 String callerPackage, Intent intent, String resolvedType,
11146 IIntentReceiver resultTo, int resultCode, String resultData,
11147 Bundle map, String requiredPermission,
11148 boolean ordered, boolean sticky, int callingPid, int callingUid) {
11149 intent = new Intent(intent);
11150
Dianne Hackborne7f97212011-02-24 14:40:20 -080011151 // By default broadcasts do not go to stopped apps.
11152 intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
11153
Joe Onorato8a9b2202010-02-26 18:56:32 -080011154 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011155 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
11156 + " ordered=" + ordered);
11157 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011158 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011159 }
11160
11161 // Handle special intents: if this broadcast is from the package
11162 // manager about a package being removed, we need to remove all of
11163 // its activities from the history stack.
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011164 final boolean uidRemoved = Intent.ACTION_UID_REMOVED.equals(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011165 intent.getAction());
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011166 if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
11167 || Intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080011168 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011169 || uidRemoved) {
11170 if (checkComponentPermission(
11171 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011172 callingPid, callingUid, -1, true)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011173 == PackageManager.PERMISSION_GRANTED) {
11174 if (uidRemoved) {
11175 final Bundle intentExtras = intent.getExtras();
11176 final int uid = intentExtras != null
11177 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
11178 if (uid >= 0) {
11179 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
11180 synchronized (bs) {
11181 bs.removeUidStatsLocked(uid);
11182 }
11183 }
11184 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011185 // If resources are unvailble just force stop all
11186 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080011187 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011188 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
11189 if (list != null && (list.length > 0)) {
11190 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011191 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011192 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070011193 sendPackageBroadcastLocked(
11194 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011195 }
11196 } else {
11197 Uri data = intent.getData();
11198 String ssp;
11199 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
11200 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
11201 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011202 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070011203 }
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011204 if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070011205 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
11206 new String[] {ssp});
11207 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011208 }
11209 }
11210 }
11211 } else {
11212 String msg = "Permission Denial: " + intent.getAction()
11213 + " broadcast from " + callerPackage + " (pid=" + callingPid
11214 + ", uid=" + callingUid + ")"
11215 + " requires "
11216 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011217 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011218 throw new SecurityException(msg);
11219 }
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011220
11221 // Special case for adding a package: by default turn on compatibility
11222 // mode.
11223 } else if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())) {
Dianne Hackborn8ea5e1d2011-05-27 16:45:31 -070011224 Uri data = intent.getData();
11225 String ssp;
11226 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
11227 mCompatModePackages.handlePackageAddedLocked(ssp,
11228 intent.getBooleanExtra(Intent.EXTRA_REPLACING, false));
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011229 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011230 }
11231
11232 /*
11233 * If this is the time zone changed action, queue up a message that will reset the timezone
11234 * of all currently running processes. This message will get queued up before the broadcast
11235 * happens.
11236 */
11237 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
11238 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
11239 }
11240
Robert Greenwalt03595d02010-11-02 14:08:23 -070011241 if (intent.ACTION_CLEAR_DNS_CACHE.equals(intent.getAction())) {
11242 mHandler.sendEmptyMessage(CLEAR_DNS_CACHE);
11243 }
11244
Robert Greenwalt434203a2010-10-11 16:00:27 -070011245 if (Proxy.PROXY_CHANGE_ACTION.equals(intent.getAction())) {
11246 ProxyProperties proxy = intent.getParcelableExtra("proxy");
11247 mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY, proxy));
11248 }
11249
Dianne Hackborn854060af2009-07-09 18:14:31 -070011250 /*
11251 * Prevent non-system code (defined here to be non-persistent
11252 * processes) from sending protected broadcasts.
11253 */
11254 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
11255 || callingUid == Process.SHELL_UID || callingUid == 0) {
11256 // Always okay.
11257 } else if (callerApp == null || !callerApp.persistent) {
11258 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011259 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -070011260 intent.getAction())) {
11261 String msg = "Permission Denial: not allowed to send broadcast "
11262 + intent.getAction() + " from pid="
11263 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011264 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070011265 throw new SecurityException(msg);
11266 }
11267 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011268 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070011269 return BROADCAST_SUCCESS;
11270 }
11271 }
11272
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011273 // Add to the sticky list if requested.
11274 if (sticky) {
11275 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
11276 callingPid, callingUid)
11277 != PackageManager.PERMISSION_GRANTED) {
11278 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
11279 + callingPid + ", uid=" + callingUid
11280 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011281 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011282 throw new SecurityException(msg);
11283 }
11284 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011285 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011286 + " and enforce permission " + requiredPermission);
11287 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
11288 }
11289 if (intent.getComponent() != null) {
11290 throw new SecurityException(
11291 "Sticky broadcasts can't target a specific component");
11292 }
11293 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
11294 if (list == null) {
11295 list = new ArrayList<Intent>();
11296 mStickyBroadcasts.put(intent.getAction(), list);
11297 }
11298 int N = list.size();
11299 int i;
11300 for (i=0; i<N; i++) {
11301 if (intent.filterEquals(list.get(i))) {
11302 // This sticky already exists, replace it.
11303 list.set(i, new Intent(intent));
11304 break;
11305 }
11306 }
11307 if (i >= N) {
11308 list.add(new Intent(intent));
11309 }
11310 }
11311
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011312 // Figure out who all will receive this broadcast.
11313 List receivers = null;
11314 List<BroadcastFilter> registeredReceivers = null;
11315 try {
11316 if (intent.getComponent() != null) {
11317 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011318 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070011319 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011320 if (ai != null) {
11321 receivers = new ArrayList();
11322 ResolveInfo ri = new ResolveInfo();
11323 ri.activityInfo = ai;
11324 receivers.add(ri);
11325 }
11326 } else {
11327 // Need to resolve the intent to interested receivers...
11328 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
11329 == 0) {
11330 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011331 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011332 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011333 }
Mihai Preda074edef2009-05-18 17:13:31 +020011334 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011335 }
11336 } catch (RemoteException ex) {
11337 // pm is in same process, this will never happen.
11338 }
11339
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011340 final boolean replacePending =
11341 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
11342
Joe Onorato8a9b2202010-02-26 18:56:32 -080011343 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011344 + " replacePending=" + replacePending);
11345
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011346 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
11347 if (!ordered && NR > 0) {
11348 // If we are not serializing this broadcast, then send the
11349 // registered receivers separately so they don't wait for the
11350 // components to be launched.
11351 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
11352 callerPackage, callingPid, callingUid, requiredPermission,
11353 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011354 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011355 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011356 TAG, "Enqueueing parallel broadcast " + r
11357 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011358 boolean replaced = false;
11359 if (replacePending) {
11360 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
11361 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011362 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011363 "***** DROPPING PARALLEL: " + intent);
11364 mParallelBroadcasts.set(i, r);
11365 replaced = true;
11366 break;
11367 }
11368 }
11369 }
11370 if (!replaced) {
11371 mParallelBroadcasts.add(r);
11372 scheduleBroadcastsLocked();
11373 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011374 registeredReceivers = null;
11375 NR = 0;
11376 }
11377
11378 // Merge into one list.
11379 int ir = 0;
11380 if (receivers != null) {
11381 // A special case for PACKAGE_ADDED: do not allow the package
11382 // being added to see this broadcast. This prevents them from
11383 // using this as a back door to get run as soon as they are
11384 // installed. Maybe in the future we want to have a special install
11385 // broadcast or such for apps, but we'd like to deliberately make
11386 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011387 String skipPackages[] = null;
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011388 if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
11389 || Intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
11390 || Intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011391 Uri data = intent.getData();
11392 if (data != null) {
11393 String pkgName = data.getSchemeSpecificPart();
11394 if (pkgName != null) {
11395 skipPackages = new String[] { pkgName };
11396 }
11397 }
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011398 } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011399 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070011400 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011401 if (skipPackages != null && (skipPackages.length > 0)) {
11402 for (String skipPackage : skipPackages) {
11403 if (skipPackage != null) {
11404 int NT = receivers.size();
11405 for (int it=0; it<NT; it++) {
11406 ResolveInfo curt = (ResolveInfo)receivers.get(it);
11407 if (curt.activityInfo.packageName.equals(skipPackage)) {
11408 receivers.remove(it);
11409 it--;
11410 NT--;
11411 }
11412 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011413 }
11414 }
11415 }
11416
11417 int NT = receivers != null ? receivers.size() : 0;
11418 int it = 0;
11419 ResolveInfo curt = null;
11420 BroadcastFilter curr = null;
11421 while (it < NT && ir < NR) {
11422 if (curt == null) {
11423 curt = (ResolveInfo)receivers.get(it);
11424 }
11425 if (curr == null) {
11426 curr = registeredReceivers.get(ir);
11427 }
11428 if (curr.getPriority() >= curt.priority) {
11429 // Insert this broadcast record into the final list.
11430 receivers.add(it, curr);
11431 ir++;
11432 curr = null;
11433 it++;
11434 NT++;
11435 } else {
11436 // Skip to the next ResolveInfo in the final list.
11437 it++;
11438 curt = null;
11439 }
11440 }
11441 }
11442 while (ir < NR) {
11443 if (receivers == null) {
11444 receivers = new ArrayList();
11445 }
11446 receivers.add(registeredReceivers.get(ir));
11447 ir++;
11448 }
11449
11450 if ((receivers != null && receivers.size() > 0)
11451 || resultTo != null) {
11452 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
11453 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011454 receivers, resultTo, resultCode, resultData, map, ordered,
11455 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011456 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011457 TAG, "Enqueueing ordered broadcast " + r
11458 + ": prev had " + mOrderedBroadcasts.size());
11459 if (DEBUG_BROADCAST) {
11460 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011461 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011462 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011463 boolean replaced = false;
11464 if (replacePending) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011465 for (int i=mOrderedBroadcasts.size()-1; i>0; i--) {
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011466 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011467 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011468 "***** DROPPING ORDERED: " + intent);
11469 mOrderedBroadcasts.set(i, r);
11470 replaced = true;
11471 break;
11472 }
11473 }
11474 }
11475 if (!replaced) {
11476 mOrderedBroadcasts.add(r);
11477 scheduleBroadcastsLocked();
11478 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011479 }
11480
11481 return BROADCAST_SUCCESS;
11482 }
11483
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011484 final Intent verifyBroadcastLocked(Intent intent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011485 // Refuse possible leaked file descriptors
11486 if (intent != null && intent.hasFileDescriptors() == true) {
11487 throw new IllegalArgumentException("File descriptors passed in Intent");
11488 }
11489
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011490 int flags = intent.getFlags();
11491
11492 if (!mProcessesReady) {
11493 // if the caller really truly claims to know what they're doing, go
11494 // ahead and allow the broadcast without launching any receivers
11495 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
11496 intent = new Intent(intent);
11497 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
11498 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
11499 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
11500 + " before boot completion");
11501 throw new IllegalStateException("Cannot broadcast before boot completed");
11502 }
11503 }
11504
11505 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
11506 throw new IllegalArgumentException(
11507 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
11508 }
11509
11510 return intent;
11511 }
11512
11513 public final int broadcastIntent(IApplicationThread caller,
11514 Intent intent, String resolvedType, IIntentReceiver resultTo,
11515 int resultCode, String resultData, Bundle map,
11516 String requiredPermission, boolean serialized, boolean sticky) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011517 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011518 intent = verifyBroadcastLocked(intent);
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011519
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011520 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11521 final int callingPid = Binder.getCallingPid();
11522 final int callingUid = Binder.getCallingUid();
11523 final long origId = Binder.clearCallingIdentity();
11524 int res = broadcastIntentLocked(callerApp,
11525 callerApp != null ? callerApp.info.packageName : null,
11526 intent, resolvedType, resultTo,
11527 resultCode, resultData, map, requiredPermission, serialized,
11528 sticky, callingPid, callingUid);
11529 Binder.restoreCallingIdentity(origId);
11530 return res;
11531 }
11532 }
11533
11534 int broadcastIntentInPackage(String packageName, int uid,
11535 Intent intent, String resolvedType, IIntentReceiver resultTo,
11536 int resultCode, String resultData, Bundle map,
11537 String requiredPermission, boolean serialized, boolean sticky) {
11538 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011539 intent = verifyBroadcastLocked(intent);
11540
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011541 final long origId = Binder.clearCallingIdentity();
11542 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
11543 resultTo, resultCode, resultData, map, requiredPermission,
11544 serialized, sticky, -1, uid);
11545 Binder.restoreCallingIdentity(origId);
11546 return res;
11547 }
11548 }
11549
11550 public final void unbroadcastIntent(IApplicationThread caller,
11551 Intent intent) {
11552 // Refuse possible leaked file descriptors
11553 if (intent != null && intent.hasFileDescriptors() == true) {
11554 throw new IllegalArgumentException("File descriptors passed in Intent");
11555 }
11556
11557 synchronized(this) {
11558 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
11559 != PackageManager.PERMISSION_GRANTED) {
11560 String msg = "Permission Denial: unbroadcastIntent() from pid="
11561 + Binder.getCallingPid()
11562 + ", uid=" + Binder.getCallingUid()
11563 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011564 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011565 throw new SecurityException(msg);
11566 }
11567 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
11568 if (list != null) {
11569 int N = list.size();
11570 int i;
11571 for (i=0; i<N; i++) {
11572 if (intent.filterEquals(list.get(i))) {
11573 list.remove(i);
11574 break;
11575 }
11576 }
11577 }
11578 }
11579 }
11580
11581 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
11582 String resultData, Bundle resultExtras, boolean resultAbort,
11583 boolean explicit) {
11584 if (mOrderedBroadcasts.size() == 0) {
11585 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011586 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011587 }
11588 return false;
11589 }
11590 BroadcastRecord r = mOrderedBroadcasts.get(0);
11591 if (r.receiver == null) {
11592 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011593 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011594 }
11595 return false;
11596 }
11597 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011598 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011599 return false;
11600 }
11601 int state = r.state;
Dianne Hackbornce86ba82011-07-13 19:33:41 -070011602 r.state = BroadcastRecord.IDLE;
11603 if (state == BroadcastRecord.IDLE) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011604 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011605 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011606 }
11607 }
11608 r.receiver = null;
11609 r.intent.setComponent(null);
11610 if (r.curApp != null) {
11611 r.curApp.curReceiver = null;
11612 }
11613 if (r.curFilter != null) {
11614 r.curFilter.receiverList.curBroadcast = null;
11615 }
11616 r.curFilter = null;
11617 r.curApp = null;
11618 r.curComponent = null;
11619 r.curReceiver = null;
11620 mPendingBroadcast = null;
11621
11622 r.resultCode = resultCode;
11623 r.resultData = resultData;
11624 r.resultExtras = resultExtras;
11625 r.resultAbort = resultAbort;
11626
11627 // We will process the next receiver right now if this is finishing
11628 // an app receiver (which is always asynchronous) or after we have
11629 // come back from calling a receiver.
11630 return state == BroadcastRecord.APP_RECEIVE
11631 || state == BroadcastRecord.CALL_DONE_RECEIVE;
11632 }
11633
11634 public void finishReceiver(IBinder who, int resultCode, String resultData,
11635 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011636 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011637
11638 // Refuse possible leaked file descriptors
11639 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
11640 throw new IllegalArgumentException("File descriptors passed in Bundle");
11641 }
11642
11643 boolean doNext;
11644
11645 final long origId = Binder.clearCallingIdentity();
11646
11647 synchronized(this) {
11648 doNext = finishReceiverLocked(
11649 who, resultCode, resultData, resultExtras, resultAbort, true);
11650 }
11651
11652 if (doNext) {
11653 processNextBroadcast(false);
11654 }
11655 trimApplications();
11656
11657 Binder.restoreCallingIdentity(origId);
11658 }
11659
Jeff Brown4d94a762010-09-23 11:33:28 -070011660 private final void logBroadcastReceiverDiscardLocked(BroadcastRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011661 if (r.nextReceiver > 0) {
11662 Object curReceiver = r.receivers.get(r.nextReceiver-1);
11663 if (curReceiver instanceof BroadcastFilter) {
11664 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080011665 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011666 System.identityHashCode(r),
11667 r.intent.getAction(),
11668 r.nextReceiver - 1,
11669 System.identityHashCode(bf));
11670 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080011671 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011672 System.identityHashCode(r),
11673 r.intent.getAction(),
11674 r.nextReceiver - 1,
11675 ((ResolveInfo)curReceiver).toString());
11676 }
11677 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011678 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011679 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011680 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011681 System.identityHashCode(r),
11682 r.intent.getAction(),
11683 r.nextReceiver,
11684 "NONE");
11685 }
11686 }
11687
Jeff Brown4d94a762010-09-23 11:33:28 -070011688 private final void setBroadcastTimeoutLocked(long timeoutTime) {
11689 if (! mPendingBroadcastTimeoutMessage) {
11690 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
11691 mHandler.sendMessageAtTime(msg, timeoutTime);
11692 mPendingBroadcastTimeoutMessage = true;
11693 }
11694 }
11695
11696 private final void cancelBroadcastTimeoutLocked() {
11697 if (mPendingBroadcastTimeoutMessage) {
11698 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
11699 mPendingBroadcastTimeoutMessage = false;
11700 }
11701 }
11702
11703 private final void broadcastTimeoutLocked(boolean fromMsg) {
11704 if (fromMsg) {
11705 mPendingBroadcastTimeoutMessage = false;
11706 }
11707
11708 if (mOrderedBroadcasts.size() == 0) {
11709 return;
11710 }
11711
11712 long now = SystemClock.uptimeMillis();
11713 BroadcastRecord r = mOrderedBroadcasts.get(0);
11714 if (fromMsg) {
11715 if (mDidDexOpt) {
11716 // Delay timeouts until dexopt finishes.
11717 mDidDexOpt = false;
11718 long timeoutTime = SystemClock.uptimeMillis() + BROADCAST_TIMEOUT;
11719 setBroadcastTimeoutLocked(timeoutTime);
11720 return;
11721 }
11722 if (! mProcessesReady) {
11723 // Only process broadcast timeouts if the system is ready. That way
11724 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
11725 // to do heavy lifting for system up.
11726 return;
11727 }
11728
11729 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
11730 if (timeoutTime > now) {
11731 // We can observe premature timeouts because we do not cancel and reset the
11732 // broadcast timeout message after each receiver finishes. Instead, we set up
11733 // an initial timeout then kick it down the road a little further as needed
11734 // when it expires.
11735 if (DEBUG_BROADCAST) Slog.v(TAG,
11736 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
11737 + timeoutTime);
11738 setBroadcastTimeoutLocked(timeoutTime);
11739 return;
11740 }
11741 }
11742
11743 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver
11744 + ", started " + (now - r.receiverTime) + "ms ago");
11745 r.receiverTime = now;
11746 r.anrCount++;
11747
11748 // Current receiver has passed its expiration date.
11749 if (r.nextReceiver <= 0) {
11750 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
11751 return;
11752 }
11753
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011754 ProcessRecord app = null;
11755 String anrMessage = null;
11756
Jeff Brown4d94a762010-09-23 11:33:28 -070011757 Object curReceiver = r.receivers.get(r.nextReceiver-1);
11758 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
11759 logBroadcastReceiverDiscardLocked(r);
11760 if (curReceiver instanceof BroadcastFilter) {
11761 BroadcastFilter bf = (BroadcastFilter)curReceiver;
11762 if (bf.receiverList.pid != 0
11763 && bf.receiverList.pid != MY_PID) {
11764 synchronized (this.mPidsSelfLocked) {
11765 app = this.mPidsSelfLocked.get(
11766 bf.receiverList.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011767 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011768 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011769 } else {
11770 app = r.curApp;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011771 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011772
Jeff Brown4d94a762010-09-23 11:33:28 -070011773 if (app != null) {
11774 anrMessage = "Broadcast of " + r.intent.toString();
11775 }
11776
11777 if (mPendingBroadcast == r) {
11778 mPendingBroadcast = null;
11779 }
11780
11781 // Move on to the next receiver.
11782 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
11783 r.resultExtras, r.resultAbort, true);
11784 scheduleBroadcastsLocked();
11785
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011786 if (anrMessage != null) {
Jeff Brown4d94a762010-09-23 11:33:28 -070011787 // Post the ANR to the handler since we do not want to process ANRs while
11788 // potentially holding our lock.
11789 mHandler.post(new AppNotResponding(app, anrMessage));
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011790 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011791 }
11792
11793 private final void processCurBroadcastLocked(BroadcastRecord r,
11794 ProcessRecord app) throws RemoteException {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011795 if (DEBUG_BROADCAST) Slog.v(TAG,
11796 "Process cur broadcast " + r + " for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011797 if (app.thread == null) {
11798 throw new RemoteException();
11799 }
11800 r.receiver = app.thread.asBinder();
11801 r.curApp = app;
11802 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011803 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011804
11805 // Tell the application to launch this receiver.
11806 r.intent.setComponent(r.curComponent);
11807
11808 boolean started = false;
11809 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011810 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011811 "Delivering to component " + r.curComponent
11812 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070011813 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011814 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
Dianne Hackborne2515ee2011-04-27 18:52:56 -040011815 compatibilityInfoForPackageLocked(r.curReceiver.applicationInfo),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011816 r.resultCode, r.resultData, r.resultExtras, r.ordered);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011817 if (DEBUG_BROADCAST) Slog.v(TAG,
11818 "Process cur broadcast " + r + " DELIVERED for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011819 started = true;
11820 } finally {
11821 if (!started) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011822 if (DEBUG_BROADCAST) Slog.v(TAG,
11823 "Process cur broadcast " + r + ": NOT STARTED!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011824 r.receiver = null;
11825 r.curApp = null;
11826 app.curReceiver = null;
11827 }
11828 }
11829
11830 }
11831
Jeff Brown4d94a762010-09-23 11:33:28 -070011832 static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011833 Intent intent, int resultCode, String data, Bundle extras,
11834 boolean ordered, boolean sticky) throws RemoteException {
Jeff Brown4d94a762010-09-23 11:33:28 -070011835 // Send the intent to the receiver asynchronously using one-way binder calls.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011836 if (app != null && app.thread != null) {
11837 // If we have an app thread, do the call through that so it is
11838 // correctly ordered with other one-way calls.
11839 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011840 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011841 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011842 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011843 }
11844 }
11845
Jeff Brown4d94a762010-09-23 11:33:28 -070011846 private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011847 BroadcastFilter filter, boolean ordered) {
11848 boolean skip = false;
11849 if (filter.requiredPermission != null) {
11850 int perm = checkComponentPermission(filter.requiredPermission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011851 r.callingPid, r.callingUid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011852 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011853 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011854 + r.intent.toString()
11855 + " from " + r.callerPackage + " (pid="
11856 + r.callingPid + ", uid=" + r.callingUid + ")"
11857 + " requires " + filter.requiredPermission
11858 + " due to registered receiver " + filter);
11859 skip = true;
11860 }
11861 }
11862 if (r.requiredPermission != null) {
11863 int perm = checkComponentPermission(r.requiredPermission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011864 filter.receiverList.pid, filter.receiverList.uid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011865 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011866 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011867 + r.intent.toString()
11868 + " to " + filter.receiverList.app
11869 + " (pid=" + filter.receiverList.pid
11870 + ", uid=" + filter.receiverList.uid + ")"
11871 + " requires " + r.requiredPermission
11872 + " due to sender " + r.callerPackage
11873 + " (uid " + r.callingUid + ")");
11874 skip = true;
11875 }
11876 }
11877
11878 if (!skip) {
11879 // If this is not being sent as an ordered broadcast, then we
11880 // don't want to touch the fields that keep track of the current
11881 // state of ordered broadcasts.
11882 if (ordered) {
11883 r.receiver = filter.receiverList.receiver.asBinder();
11884 r.curFilter = filter;
11885 filter.receiverList.curBroadcast = r;
11886 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011887 if (filter.receiverList.app != null) {
11888 // Bump hosting application to no longer be in background
11889 // scheduling class. Note that we can't do that if there
11890 // isn't an app... but we can only be in that case for
11891 // things that directly call the IActivityManager API, which
11892 // are already core system stuff so don't matter for this.
11893 r.curApp = filter.receiverList.app;
11894 filter.receiverList.app.curReceiver = r;
11895 updateOomAdjLocked();
11896 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011897 }
11898 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011899 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011900 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011901 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011902 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011903 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011904 performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011905 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011906 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011907 if (ordered) {
11908 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
11909 }
11910 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011911 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011912 if (ordered) {
11913 r.receiver = null;
11914 r.curFilter = null;
11915 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011916 if (filter.receiverList.app != null) {
11917 filter.receiverList.app.curReceiver = null;
11918 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011919 }
11920 }
11921 }
11922 }
11923
Dianne Hackborn12527f92009-11-11 17:39:50 -080011924 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
11925 if (r.callingUid < 0) {
11926 // This was from a registerReceiver() call; ignore it.
11927 return;
11928 }
11929 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
11930 MAX_BROADCAST_HISTORY-1);
11931 r.finishTime = SystemClock.uptimeMillis();
11932 mBroadcastHistory[0] = r;
11933 }
11934
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011935 private final void processNextBroadcast(boolean fromMsg) {
11936 synchronized(this) {
11937 BroadcastRecord r;
11938
Joe Onorato8a9b2202010-02-26 18:56:32 -080011939 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011940 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011941 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011942
11943 updateCpuStats();
11944
11945 if (fromMsg) {
11946 mBroadcastsScheduled = false;
11947 }
11948
11949 // First, deliver any non-serialized broadcasts right away.
11950 while (mParallelBroadcasts.size() > 0) {
11951 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080011952 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011953 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011954 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011955 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011956 for (int i=0; i<N; i++) {
11957 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011958 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011959 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011960 + target + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011961 deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011962 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080011963 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011964 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011965 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011966 }
11967
11968 // Now take care of the next serialized one...
11969
11970 // If we are waiting for a process to come up to handle the next
11971 // broadcast, then do nothing at this point. Just in case, we
11972 // check that the process we're waiting for still exists.
11973 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070011974 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011975 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070011976 + mPendingBroadcast.curApp);
11977 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011978
11979 boolean isDead;
11980 synchronized (mPidsSelfLocked) {
11981 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
11982 }
11983 if (!isDead) {
11984 // It's still alive, so keep waiting
11985 return;
11986 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011987 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011988 + " died before responding to broadcast");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011989 mPendingBroadcast.state = BroadcastRecord.IDLE;
11990 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011991 mPendingBroadcast = null;
11992 }
11993 }
11994
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011995 boolean looped = false;
11996
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011997 do {
11998 if (mOrderedBroadcasts.size() == 0) {
11999 // No more broadcasts pending, so all done!
12000 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012001 if (looped) {
12002 // If we had finished the last ordered broadcast, then
12003 // make sure all processes have correct oom and sched
12004 // adjustments.
12005 updateOomAdjLocked();
12006 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012007 return;
12008 }
12009 r = mOrderedBroadcasts.get(0);
12010 boolean forceReceive = false;
12011
12012 // Ensure that even if something goes awry with the timeout
12013 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050012014 // and continue to make progress.
12015 //
12016 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
Jeff Brown4d94a762010-09-23 11:33:28 -070012017 // receivers don't get executed with timeouts. They're intended for
Jeff Hamiltonacf84742010-05-25 22:10:18 -050012018 // one time heavy lifting after system upgrades and can take
12019 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012020 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012021 if (mProcessesReady && r.dispatchTime > 0) {
Jeff Hamiltonacf84742010-05-25 22:10:18 -050012022 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012023 if ((numReceivers > 0) &&
12024 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012025 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012026 + " now=" + now
12027 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080012028 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012029 + " intent=" + r.intent
12030 + " numReceivers=" + numReceivers
12031 + " nextReceiver=" + r.nextReceiver
12032 + " state=" + r.state);
Jeff Brown4d94a762010-09-23 11:33:28 -070012033 broadcastTimeoutLocked(false); // forcibly finish this broadcast
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012034 forceReceive = true;
12035 r.state = BroadcastRecord.IDLE;
12036 }
12037 }
12038
12039 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012040 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012041 "processNextBroadcast() called when not idle (state="
12042 + r.state + ")");
12043 return;
12044 }
12045
12046 if (r.receivers == null || r.nextReceiver >= numReceivers
12047 || r.resultAbort || forceReceive) {
12048 // No more receivers for this broadcast! Send the final
12049 // result if requested...
12050 if (r.resultTo != null) {
12051 try {
12052 if (DEBUG_BROADCAST) {
12053 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012054 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012055 + " seq=" + seq + " app=" + r.callerApp);
12056 }
Jeff Brown4d94a762010-09-23 11:33:28 -070012057 performReceiveLocked(r.callerApp, r.resultTo,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012058 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012059 r.resultData, r.resultExtras, false, false);
Johannes Carlssonb5a86542010-10-27 10:08:10 +020012060 // Set this to null so that the reference
12061 // (local and remote) isnt kept in the mBroadcastHistory.
12062 r.resultTo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012063 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012064 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012065 }
12066 }
12067
Joe Onorato8a9b2202010-02-26 18:56:32 -080012068 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
Jeff Brown4d94a762010-09-23 11:33:28 -070012069 cancelBroadcastTimeoutLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012070
Joe Onorato8a9b2202010-02-26 18:56:32 -080012071 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012072 + r);
12073
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012074 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080012075 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012076 mOrderedBroadcasts.remove(0);
12077 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012078 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012079 continue;
12080 }
12081 } while (r == null);
12082
12083 // Get the next receiver...
12084 int recIdx = r.nextReceiver++;
12085
12086 // Keep track of when this receiver started, and make sure there
12087 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080012088 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012089 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080012090 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012091
Joe Onorato8a9b2202010-02-26 18:56:32 -080012092 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012093 + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070012094 }
12095 if (! mPendingBroadcastTimeoutMessage) {
12096 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012097 if (DEBUG_BROADCAST) Slog.v(TAG,
Jeff Brown4d94a762010-09-23 11:33:28 -070012098 "Submitting BROADCAST_TIMEOUT_MSG for " + r + " at " + timeoutTime);
12099 setBroadcastTimeoutLocked(timeoutTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012100 }
12101
12102 Object nextReceiver = r.receivers.get(recIdx);
12103 if (nextReceiver instanceof BroadcastFilter) {
12104 // Simple case: this is a registered receiver who gets
12105 // a direct call.
12106 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012107 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070012108 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012109 + filter + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070012110 deliverToRegisteredReceiverLocked(r, filter, r.ordered);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012111 if (r.receiver == null || !r.ordered) {
12112 // The receiver has already finished, so schedule to
12113 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070012114 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
12115 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012116 r.state = BroadcastRecord.IDLE;
12117 scheduleBroadcastsLocked();
12118 }
12119 return;
12120 }
12121
12122 // Hard case: need to instantiate the receiver, possibly
12123 // starting its application process to host it.
12124
12125 ResolveInfo info =
12126 (ResolveInfo)nextReceiver;
12127
12128 boolean skip = false;
12129 int perm = checkComponentPermission(info.activityInfo.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080012130 r.callingPid, r.callingUid, info.activityInfo.applicationInfo.uid,
12131 info.activityInfo.exported);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012132 if (perm != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080012133 if (!info.activityInfo.exported) {
12134 Slog.w(TAG, "Permission Denial: broadcasting "
12135 + r.intent.toString()
12136 + " from " + r.callerPackage + " (pid=" + r.callingPid
12137 + ", uid=" + r.callingUid + ")"
12138 + " is not exported from uid " + info.activityInfo.applicationInfo.uid
12139 + " due to receiver " + info.activityInfo.packageName
12140 + "/" + info.activityInfo.name);
12141 } else {
12142 Slog.w(TAG, "Permission Denial: broadcasting "
12143 + r.intent.toString()
12144 + " from " + r.callerPackage + " (pid=" + r.callingPid
12145 + ", uid=" + r.callingUid + ")"
12146 + " requires " + info.activityInfo.permission
12147 + " due to receiver " + info.activityInfo.packageName
12148 + "/" + info.activityInfo.name);
12149 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012150 skip = true;
12151 }
12152 if (r.callingUid != Process.SYSTEM_UID &&
12153 r.requiredPermission != null) {
12154 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012155 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012156 checkPermission(r.requiredPermission,
12157 info.activityInfo.applicationInfo.packageName);
12158 } catch (RemoteException e) {
12159 perm = PackageManager.PERMISSION_DENIED;
12160 }
12161 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012162 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012163 + r.intent + " to "
12164 + info.activityInfo.applicationInfo.packageName
12165 + " requires " + r.requiredPermission
12166 + " due to sender " + r.callerPackage
12167 + " (uid " + r.callingUid + ")");
12168 skip = true;
12169 }
12170 }
12171 if (r.curApp != null && r.curApp.crashing) {
12172 // If the target process is crashing, just skip it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012173 if (DEBUG_BROADCAST) Slog.v(TAG,
12174 "Skipping deliver ordered " + r + " to " + r.curApp
12175 + ": process crashing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012176 skip = true;
12177 }
12178
12179 if (skip) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012180 if (DEBUG_BROADCAST) Slog.v(TAG,
12181 "Skipping delivery of ordered " + r + " for whatever reason");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012182 r.receiver = null;
12183 r.curFilter = null;
12184 r.state = BroadcastRecord.IDLE;
12185 scheduleBroadcastsLocked();
12186 return;
12187 }
12188
12189 r.state = BroadcastRecord.APP_RECEIVE;
12190 String targetProcess = info.activityInfo.processName;
12191 r.curComponent = new ComponentName(
12192 info.activityInfo.applicationInfo.packageName,
12193 info.activityInfo.name);
12194 r.curReceiver = info.activityInfo;
12195
Dianne Hackborne7f97212011-02-24 14:40:20 -080012196 // Broadcast is being executed, its package can't be stopped.
12197 try {
12198 AppGlobals.getPackageManager().setPackageStoppedState(
12199 r.curComponent.getPackageName(), false);
12200 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -080012201 } catch (IllegalArgumentException e) {
12202 Slog.w(TAG, "Failed trying to unstop package "
12203 + r.curComponent.getPackageName() + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -080012204 }
12205
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012206 // Is this receiver's application already running?
12207 ProcessRecord app = getProcessRecordLocked(targetProcess,
12208 info.activityInfo.applicationInfo.uid);
12209 if (app != null && app.thread != null) {
12210 try {
Dianne Hackborn6c418d52011-06-29 14:05:33 -070012211 app.addPackage(info.activityInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012212 processCurBroadcastLocked(r, app);
12213 return;
12214 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012215 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012216 + r.curComponent, e);
12217 }
12218
12219 // If a dead object exception was thrown -- fall through to
12220 // restart the application.
12221 }
12222
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012223 // Not running -- get it started, to be executed when the app comes up.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012224 if (DEBUG_BROADCAST) Slog.v(TAG,
12225 "Need to start app " + targetProcess + " for broadcast " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012226 if ((r.curApp=startProcessLocked(targetProcess,
12227 info.activityInfo.applicationInfo, true,
12228 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012229 "broadcast", r.curComponent,
12230 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
12231 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012232 // Ah, this recipient is unavailable. Finish it if necessary,
12233 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012234 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012235 + info.activityInfo.applicationInfo.packageName + "/"
12236 + info.activityInfo.applicationInfo.uid + " for broadcast "
12237 + r.intent + ": process is bad");
Jeff Brown4d94a762010-09-23 11:33:28 -070012238 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012239 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
12240 r.resultExtras, r.resultAbort, true);
12241 scheduleBroadcastsLocked();
12242 r.state = BroadcastRecord.IDLE;
12243 return;
12244 }
12245
12246 mPendingBroadcast = r;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012247 mPendingBroadcastRecvIndex = recIdx;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012248 }
12249 }
12250
12251 // =========================================================
12252 // INSTRUMENTATION
12253 // =========================================================
12254
12255 public boolean startInstrumentation(ComponentName className,
12256 String profileFile, int flags, Bundle arguments,
12257 IInstrumentationWatcher watcher) {
12258 // Refuse possible leaked file descriptors
12259 if (arguments != null && arguments.hasFileDescriptors()) {
12260 throw new IllegalArgumentException("File descriptors passed in Bundle");
12261 }
12262
12263 synchronized(this) {
12264 InstrumentationInfo ii = null;
12265 ApplicationInfo ai = null;
12266 try {
12267 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012268 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012269 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012270 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012271 } catch (PackageManager.NameNotFoundException e) {
12272 }
12273 if (ii == null) {
12274 reportStartInstrumentationFailure(watcher, className,
12275 "Unable to find instrumentation info for: " + className);
12276 return false;
12277 }
12278 if (ai == null) {
12279 reportStartInstrumentationFailure(watcher, className,
12280 "Unable to find instrumentation target package: " + ii.targetPackage);
12281 return false;
12282 }
12283
12284 int match = mContext.getPackageManager().checkSignatures(
12285 ii.targetPackage, ii.packageName);
12286 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
12287 String msg = "Permission Denial: starting instrumentation "
12288 + className + " from pid="
12289 + Binder.getCallingPid()
12290 + ", uid=" + Binder.getCallingPid()
12291 + " not allowed because package " + ii.packageName
12292 + " does not have a signature matching the target "
12293 + ii.targetPackage;
12294 reportStartInstrumentationFailure(watcher, className, msg);
12295 throw new SecurityException(msg);
12296 }
12297
12298 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012299 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012300 ProcessRecord app = addAppLocked(ai);
12301 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070012302 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012303 app.instrumentationProfileFile = profileFile;
12304 app.instrumentationArguments = arguments;
12305 app.instrumentationWatcher = watcher;
12306 app.instrumentationResultClass = className;
12307 Binder.restoreCallingIdentity(origId);
12308 }
12309
12310 return true;
12311 }
12312
12313 /**
12314 * Report errors that occur while attempting to start Instrumentation. Always writes the
12315 * error to the logs, but if somebody is watching, send the report there too. This enables
12316 * the "am" command to report errors with more information.
12317 *
12318 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
12319 * @param cn The component name of the instrumentation.
12320 * @param report The error report.
12321 */
12322 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
12323 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012324 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012325 try {
12326 if (watcher != null) {
12327 Bundle results = new Bundle();
12328 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
12329 results.putString("Error", report);
12330 watcher.instrumentationStatus(cn, -1, results);
12331 }
12332 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012333 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012334 }
12335 }
12336
12337 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
12338 if (app.instrumentationWatcher != null) {
12339 try {
12340 // NOTE: IInstrumentationWatcher *must* be oneway here
12341 app.instrumentationWatcher.instrumentationFinished(
12342 app.instrumentationClass,
12343 resultCode,
12344 results);
12345 } catch (RemoteException e) {
12346 }
12347 }
12348 app.instrumentationWatcher = null;
12349 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070012350 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012351 app.instrumentationProfileFile = null;
12352 app.instrumentationArguments = null;
12353
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012354 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012355 }
12356
12357 public void finishInstrumentation(IApplicationThread target,
12358 int resultCode, Bundle results) {
12359 // Refuse possible leaked file descriptors
12360 if (results != null && results.hasFileDescriptors()) {
12361 throw new IllegalArgumentException("File descriptors passed in Intent");
12362 }
12363
12364 synchronized(this) {
12365 ProcessRecord app = getRecordForAppLocked(target);
12366 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012367 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012368 return;
12369 }
12370 final long origId = Binder.clearCallingIdentity();
12371 finishInstrumentationLocked(app, resultCode, results);
12372 Binder.restoreCallingIdentity(origId);
12373 }
12374 }
12375
12376 // =========================================================
12377 // CONFIGURATION
12378 // =========================================================
12379
12380 public ConfigurationInfo getDeviceConfigurationInfo() {
12381 ConfigurationInfo config = new ConfigurationInfo();
12382 synchronized (this) {
12383 config.reqTouchScreen = mConfiguration.touchscreen;
12384 config.reqKeyboardType = mConfiguration.keyboard;
12385 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070012386 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
12387 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012388 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
12389 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070012390 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
12391 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012392 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
12393 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070012394 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012395 }
12396 return config;
12397 }
12398
12399 public Configuration getConfiguration() {
12400 Configuration ci;
12401 synchronized(this) {
12402 ci = new Configuration(mConfiguration);
12403 }
12404 return ci;
12405 }
12406
Dianne Hackborn31ca8542011-07-19 14:58:28 -070012407 public void updatePersistentConfiguration(Configuration values) {
12408 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
12409 "updateConfiguration()");
12410 enforceCallingPermission(android.Manifest.permission.WRITE_SETTINGS,
12411 "updateConfiguration()");
12412 if (values == null) {
12413 throw new NullPointerException("Configuration must not be null");
12414 }
12415
12416 synchronized(this) {
12417 final long origId = Binder.clearCallingIdentity();
12418 updateConfigurationLocked(values, null, true);
12419 Binder.restoreCallingIdentity(origId);
12420 }
12421 }
12422
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012423 public void updateConfiguration(Configuration values) {
12424 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
12425 "updateConfiguration()");
12426
12427 synchronized(this) {
12428 if (values == null && mWindowManager != null) {
12429 // sentinel: fetch the current configuration from the window manager
12430 values = mWindowManager.computeNewConfiguration();
12431 }
12432
12433 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn31ca8542011-07-19 14:58:28 -070012434 if (values != null) {
12435 Settings.System.clearConfiguration(values);
12436 }
12437 updateConfigurationLocked(values, null, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012438 Binder.restoreCallingIdentity(origId);
12439 }
12440 }
12441
12442 /**
12443 * Do either or both things: (1) change the current configuration, and (2)
12444 * make sure the given activity is running with the (now) current
12445 * configuration. Returns true if the activity has been left running, or
12446 * false if <var>starting</var> is being destroyed to match the new
12447 * configuration.
Dianne Hackborn31ca8542011-07-19 14:58:28 -070012448 * @param persistent TODO
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012449 */
12450 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn31ca8542011-07-19 14:58:28 -070012451 ActivityRecord starting, boolean persistent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012452 int changes = 0;
12453
12454 boolean kept = true;
12455
12456 if (values != null) {
12457 Configuration newConfig = new Configuration(mConfiguration);
12458 changes = newConfig.updateFrom(values);
12459 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070012460 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012461 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012462 }
12463
Doug Zongker2bec3d42009-12-04 12:52:44 -080012464 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012465
12466 if (values.locale != null) {
12467 saveLocaleLocked(values.locale,
12468 !values.locale.equals(mConfiguration.locale),
12469 values.userSetLocale);
12470 }
12471
Dianne Hackborne36d6e22010-02-17 19:46:25 -080012472 mConfigurationSeq++;
12473 if (mConfigurationSeq <= 0) {
12474 mConfigurationSeq = 1;
12475 }
12476 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012477 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012478 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080012479
12480 AttributeCache ac = AttributeCache.instance();
12481 if (ac != null) {
12482 ac.updateConfiguration(mConfiguration);
12483 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012484
Dianne Hackborn2f0b1752011-05-31 17:59:49 -070012485 // Make sure all resources in our process are updated
12486 // right now, so that anyone who is going to retrieve
12487 // resource values after we return will be sure to get
12488 // the new ones. This is especially important during
12489 // boot, where the first config change needs to guarantee
12490 // all resources have that config before following boot
12491 // code is executed.
12492 mSystemThread.applyConfigurationToResources(newConfig);
12493
Dianne Hackborn31ca8542011-07-19 14:58:28 -070012494 if (persistent && Settings.System.hasInterestingConfigurationChanges(changes)) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080012495 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
12496 msg.obj = new Configuration(mConfiguration);
12497 mHandler.sendMessage(msg);
12498 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012499
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012500 for (int i=mLruProcesses.size()-1; i>=0; i--) {
12501 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012502 try {
12503 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012504 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070012505 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012506 app.thread.scheduleConfigurationChanged(mConfiguration);
12507 }
12508 } catch (Exception e) {
12509 }
12510 }
12511 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012512 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
12513 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012514 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
12515 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080012516 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
12517 broadcastIntentLocked(null, null,
12518 new Intent(Intent.ACTION_LOCALE_CHANGED),
12519 null, null, 0, null, null,
12520 null, false, false, MY_PID, Process.SYSTEM_UID);
12521 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012522 }
12523 }
12524
12525 if (changes != 0 && starting == null) {
12526 // If the configuration changed, and the caller is not already
12527 // in the process of starting an activity, then find the top
12528 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012529 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012530 }
12531
12532 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012533 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
Dianne Hackborn5f4d6432010-12-21 20:40:11 -080012534 // And we need to make sure at this point that all other activities
12535 // are made visible with the correct configuration.
12536 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012537 }
12538
Dianne Hackborne36d6e22010-02-17 19:46:25 -080012539 if (values != null && mWindowManager != null) {
12540 mWindowManager.setNewConfiguration(mConfiguration);
12541 }
12542
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012543 return kept;
12544 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012545
12546 /**
12547 * Save the locale. You must be inside a synchronized (this) block.
12548 */
12549 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
12550 if(isDiff) {
12551 SystemProperties.set("user.language", l.getLanguage());
12552 SystemProperties.set("user.region", l.getCountry());
12553 }
12554
12555 if(isPersist) {
12556 SystemProperties.set("persist.sys.language", l.getLanguage());
12557 SystemProperties.set("persist.sys.country", l.getCountry());
12558 SystemProperties.set("persist.sys.localevar", l.getVariant());
12559 }
12560 }
12561
12562 // =========================================================
12563 // LIFETIME MANAGEMENT
12564 // =========================================================
12565
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012566 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
12567 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012568 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012569 // This adjustment has already been computed. If we are calling
12570 // from the top, we may have already computed our adjustment with
12571 // an earlier hidden adjustment that isn't really for us... if
12572 // so, use the new hidden adjustment.
12573 if (!recursed && app.hidden) {
12574 app.curAdj = hiddenAdj;
12575 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012576 return app.curAdj;
12577 }
12578
12579 if (app.thread == null) {
12580 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012581 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012582 return (app.curAdj=EMPTY_APP_ADJ);
12583 }
12584
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012585 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
12586 // The max adjustment doesn't allow this app to be anything
12587 // below foreground, so it is not worth doing work for it.
12588 app.adjType = "fixed";
12589 app.adjSeq = mAdjSeq;
12590 app.curRawAdj = app.maxAdj;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012591 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012592 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
12593 return (app.curAdj=app.maxAdj);
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012594 }
12595
12596 final boolean hadForegroundActivities = app.foregroundActivities;
12597
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012598 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012599 app.adjSource = null;
12600 app.adjTarget = null;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012601 app.keeping = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012602 app.empty = false;
12603 app.hidden = false;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012604 app.foregroundActivities = false;
12605
12606 final int activitiesSize = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012607
The Android Open Source Project4df24232009-03-05 14:34:35 -080012608 // Determine the importance of the process, starting with most
12609 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012610 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012611 int schedGroup;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012612 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012613 // The last app on the list is the foreground app.
12614 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012615 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012616 app.adjType = "top-activity";
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012617 app.foregroundActivities = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012618 } else if (app.instrumentationClass != null) {
12619 // Don't want to kill running instrumentation.
12620 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012621 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012622 app.adjType = "instrumentation";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012623 } else if (app.curReceiver != null ||
12624 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
12625 // An app that is currently receiving a broadcast also
12626 // counts as being in the foreground.
12627 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012628 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012629 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012630 } else if (app.executingServices.size() > 0) {
12631 // An app that is currently executing a service callback also
12632 // counts as being in the foreground.
12633 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012634 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012635 app.adjType = "exec-service";
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012636 } else if (activitiesSize > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012637 // This app is in the background with paused activities.
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012638 // We inspect activities to potentially upgrade adjustment further below.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012639 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012640 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012641 app.hidden = true;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012642 app.adjType = "bg-activities";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012643 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012644 // A very not-needed process. If this is lower in the lru list,
12645 // we will push it in to the empty bucket.
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012646 adj = hiddenAdj;
12647 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012648 app.hidden = true;
12649 app.empty = true;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012650 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012651 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012652
12653 // Examine all activities if not already foreground.
12654 if (!app.foregroundActivities && activitiesSize > 0) {
12655 for (int j = 0; j < activitiesSize; j++) {
12656 final ActivityRecord r = app.activities.get(j);
12657 if (r.visible) {
12658 // App has a visible activity; only upgrade adjustment.
12659 if (adj > VISIBLE_APP_ADJ) {
12660 adj = VISIBLE_APP_ADJ;
12661 app.adjType = "visible";
12662 }
12663 schedGroup = Process.THREAD_GROUP_DEFAULT;
12664 app.hidden = false;
12665 app.foregroundActivities = true;
12666 break;
12667 } else if (r.state == ActivityState.PAUSING || r.state == ActivityState.PAUSED
12668 || r.state == ActivityState.STOPPING) {
12669 // Only upgrade adjustment.
12670 if (adj > PERCEPTIBLE_APP_ADJ) {
12671 adj = PERCEPTIBLE_APP_ADJ;
12672 app.adjType = "stopping";
12673 }
12674 app.foregroundActivities = true;
12675 }
12676 }
12677 }
12678
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012679 if (adj > PERCEPTIBLE_APP_ADJ) {
12680 if (app.foregroundServices) {
12681 // The user is aware of this app, so make it visible.
12682 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012683 app.adjType = "foreground-service";
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012684 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012685 } else if (app.forcingToForeground != null) {
12686 // The user is aware of this app, so make it visible.
12687 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012688 app.adjType = "force-foreground";
12689 app.adjSource = app.forcingToForeground;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012690 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012691 }
12692 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012693
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012694 if (adj > HEAVY_WEIGHT_APP_ADJ && app == mHeavyWeightProcess) {
12695 // We don't want to kill the current heavy-weight process.
12696 adj = HEAVY_WEIGHT_APP_ADJ;
12697 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
12698 app.adjType = "heavy";
12699 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012700
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012701 if (adj > HOME_APP_ADJ && app == mHomeProcess) {
12702 // This process is hosting what we currently consider to be the
12703 // home app, so we don't want to let it go into the background.
12704 adj = HOME_APP_ADJ;
12705 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
12706 app.adjType = "home";
12707 }
12708
Joe Onorato8a9b2202010-02-26 18:56:32 -080012709 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012710
The Android Open Source Project4df24232009-03-05 14:34:35 -080012711 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012712 // there are applications dependent on our services or providers, but
12713 // this gives us a baseline and makes sure we don't get into an
12714 // infinite recursion.
12715 app.adjSeq = mAdjSeq;
12716 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012717
Christopher Tate6fa95972009-06-05 18:43:55 -070012718 if (mBackupTarget != null && app == mBackupTarget.app) {
12719 // If possible we want to avoid killing apps while they're being backed up
12720 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012721 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070012722 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012723 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012724 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070012725 }
12726 }
12727
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012728 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
12729 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012730 final long now = SystemClock.uptimeMillis();
12731 // This process is more important if the top activity is
12732 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070012733 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012734 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012735 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012736 if (s.startRequested) {
Dianne Hackbornf0754f5b2011-07-21 16:02:07 -070012737 if (app.hasShownUi) {
12738 // If this process has shown some UI, let it immediately
12739 // go to the LRU list because it may be pretty heavy with
12740 // UI stuff. We'll tag it with a label just to help
12741 // debug and understand what is going on.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012742 if (adj > SECONDARY_SERVER_ADJ) {
Dianne Hackbornf0754f5b2011-07-21 16:02:07 -070012743 app.adjType = "started-bg-ui-services";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012744 }
Dianne Hackbornf0754f5b2011-07-21 16:02:07 -070012745 } else {
12746 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
12747 // This service has seen some activity within
12748 // recent memory, so we will keep its process ahead
12749 // of the background processes.
12750 if (adj > SECONDARY_SERVER_ADJ) {
12751 adj = SECONDARY_SERVER_ADJ;
12752 app.adjType = "started-services";
12753 app.hidden = false;
12754 }
12755 }
12756 // If we have let the service slide into the background
12757 // state, still have some text describing what it is doing
12758 // even though the service no longer has an impact.
12759 if (adj > SECONDARY_SERVER_ADJ) {
12760 app.adjType = "started-bg-services";
12761 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012762 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012763 // Don't kill this process because it is doing work; it
12764 // has said it is doing work.
12765 app.keeping = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012766 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012767 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
12768 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012769 Iterator<ArrayList<ConnectionRecord>> kt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012770 = s.connections.values().iterator();
12771 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012772 ArrayList<ConnectionRecord> clist = kt.next();
12773 for (int i=0; i<clist.size() && adj > FOREGROUND_APP_ADJ; i++) {
12774 // XXX should compute this based on the max of
12775 // all connected clients.
12776 ConnectionRecord cr = clist.get(i);
12777 if (cr.binding.client == app) {
12778 // Binding to ourself is not interesting.
12779 continue;
12780 }
12781 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
12782 ProcessRecord client = cr.binding.client;
12783 int myHiddenAdj = hiddenAdj;
12784 if (myHiddenAdj > client.hiddenAdj) {
12785 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
12786 myHiddenAdj = client.hiddenAdj;
12787 } else {
12788 myHiddenAdj = VISIBLE_APP_ADJ;
12789 }
12790 }
12791 int clientAdj = computeOomAdjLocked(
12792 client, myHiddenAdj, TOP_APP, true);
12793 if (adj > clientAdj) {
12794 adj = clientAdj >= VISIBLE_APP_ADJ
12795 ? clientAdj : VISIBLE_APP_ADJ;
12796 if (!client.hidden) {
12797 app.hidden = false;
12798 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012799 if (client.keeping) {
12800 app.keeping = true;
12801 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012802 app.adjType = "service";
12803 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12804 .REASON_SERVICE_IN_USE;
12805 app.adjSource = cr.binding.client;
12806 app.adjTarget = s.name;
12807 }
12808 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
12809 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
12810 schedGroup = Process.THREAD_GROUP_DEFAULT;
12811 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012812 }
12813 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012814 ActivityRecord a = cr.activity;
12815 //if (a != null) {
12816 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
12817 //}
12818 if (a != null && adj > FOREGROUND_APP_ADJ &&
12819 (a.state == ActivityState.RESUMED
12820 || a.state == ActivityState.PAUSING)) {
12821 adj = FOREGROUND_APP_ADJ;
12822 schedGroup = Process.THREAD_GROUP_DEFAULT;
12823 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012824 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012825 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12826 .REASON_SERVICE_IN_USE;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012827 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012828 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012829 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012830 }
12831 }
12832 }
12833 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012834
Dianne Hackborn287952c2010-09-22 22:34:31 -070012835 // Finally, if this process has active services running in it, we
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012836 // would like to avoid killing it unless it would prevent the current
12837 // application from running. By default we put the process in
12838 // with the rest of the background processes; as we scan through
12839 // its services we may bump it up from there.
12840 if (adj > hiddenAdj) {
12841 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012842 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012843 app.adjType = "bg-services";
12844 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012845 }
12846
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012847 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
12848 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012849 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012850 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
12851 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012852 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012853 if (cpr.clients.size() != 0) {
12854 Iterator<ProcessRecord> kt = cpr.clients.iterator();
12855 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
12856 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070012857 if (client == app) {
12858 // Being our own client is not interesting.
12859 continue;
12860 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012861 int myHiddenAdj = hiddenAdj;
12862 if (myHiddenAdj > client.hiddenAdj) {
12863 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
12864 myHiddenAdj = client.hiddenAdj;
12865 } else {
12866 myHiddenAdj = FOREGROUND_APP_ADJ;
12867 }
12868 }
12869 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012870 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012871 if (adj > clientAdj) {
12872 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012873 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012874 if (!client.hidden) {
12875 app.hidden = false;
12876 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012877 if (client.keeping) {
12878 app.keeping = true;
12879 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012880 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012881 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12882 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012883 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012884 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012885 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012886 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
12887 schedGroup = Process.THREAD_GROUP_DEFAULT;
12888 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012889 }
12890 }
12891 // If the provider has external (non-framework) process
12892 // dependencies, ensure that its adjustment is at least
12893 // FOREGROUND_APP_ADJ.
12894 if (cpr.externals != 0) {
12895 if (adj > FOREGROUND_APP_ADJ) {
12896 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012897 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012898 app.hidden = false;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012899 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012900 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012901 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012902 }
12903 }
12904 }
12905 }
12906
12907 app.curRawAdj = adj;
12908
Joe Onorato8a9b2202010-02-26 18:56:32 -080012909 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012910 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
12911 if (adj > app.maxAdj) {
12912 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070012913 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012914 schedGroup = Process.THREAD_GROUP_DEFAULT;
12915 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012916 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012917 if (adj < HIDDEN_APP_MIN_ADJ) {
12918 app.keeping = true;
12919 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012920
12921 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012922 app.curSchedGroup = schedGroup;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012923
12924 if (hadForegroundActivities != app.foregroundActivities) {
Jeff Sharkey287bd832011-05-28 19:36:26 -070012925 mHandler.obtainMessage(DISPATCH_FOREGROUND_ACTIVITIES_CHANGED, app.pid, app.info.uid,
12926 app.foregroundActivities).sendToTarget();
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012927 }
12928
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012929 return adj;
12930 }
12931
12932 /**
12933 * Ask a given process to GC right now.
12934 */
12935 final void performAppGcLocked(ProcessRecord app) {
12936 try {
12937 app.lastRequestedGc = SystemClock.uptimeMillis();
12938 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012939 if (app.reportLowMemory) {
12940 app.reportLowMemory = false;
12941 app.thread.scheduleLowMemory();
12942 } else {
12943 app.thread.processInBackground();
12944 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012945 }
12946 } catch (Exception e) {
12947 // whatever.
12948 }
12949 }
12950
12951 /**
12952 * Returns true if things are idle enough to perform GCs.
12953 */
Josh Bartel7f208742010-02-25 11:01:44 -060012954 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012955 return mParallelBroadcasts.size() == 0
12956 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012957 && (mSleeping || (mMainStack.mResumedActivity != null &&
12958 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012959 }
12960
12961 /**
12962 * Perform GCs on all processes that are waiting for it, but only
12963 * if things are idle.
12964 */
12965 final void performAppGcsLocked() {
12966 final int N = mProcessesToGc.size();
12967 if (N <= 0) {
12968 return;
12969 }
Josh Bartel7f208742010-02-25 11:01:44 -060012970 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012971 while (mProcessesToGc.size() > 0) {
12972 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070012973 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012974 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
12975 <= SystemClock.uptimeMillis()) {
12976 // To avoid spamming the system, we will GC processes one
12977 // at a time, waiting a few seconds between each.
12978 performAppGcLocked(proc);
12979 scheduleAppGcsLocked();
12980 return;
12981 } else {
12982 // It hasn't been long enough since we last GCed this
12983 // process... put it in the list to wait for its time.
12984 addProcessToGcListLocked(proc);
12985 break;
12986 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012987 }
12988 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012989
12990 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012991 }
12992 }
12993
12994 /**
12995 * If all looks good, perform GCs on all processes waiting for them.
12996 */
12997 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060012998 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012999 performAppGcsLocked();
13000 return;
13001 }
13002 // Still not idle, wait some more.
13003 scheduleAppGcsLocked();
13004 }
13005
13006 /**
13007 * Schedule the execution of all pending app GCs.
13008 */
13009 final void scheduleAppGcsLocked() {
13010 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013011
13012 if (mProcessesToGc.size() > 0) {
13013 // Schedule a GC for the time to the next process.
13014 ProcessRecord proc = mProcessesToGc.get(0);
13015 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
13016
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013017 long when = proc.lastRequestedGc + GC_MIN_INTERVAL;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013018 long now = SystemClock.uptimeMillis();
13019 if (when < (now+GC_TIMEOUT)) {
13020 when = now + GC_TIMEOUT;
13021 }
13022 mHandler.sendMessageAtTime(msg, when);
13023 }
13024 }
13025
13026 /**
13027 * Add a process to the array of processes waiting to be GCed. Keeps the
13028 * list in sorted order by the last GC time. The process can't already be
13029 * on the list.
13030 */
13031 final void addProcessToGcListLocked(ProcessRecord proc) {
13032 boolean added = false;
13033 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
13034 if (mProcessesToGc.get(i).lastRequestedGc <
13035 proc.lastRequestedGc) {
13036 added = true;
13037 mProcessesToGc.add(i+1, proc);
13038 break;
13039 }
13040 }
13041 if (!added) {
13042 mProcessesToGc.add(0, proc);
13043 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013044 }
13045
13046 /**
13047 * Set up to ask a process to GC itself. This will either do it
13048 * immediately, or put it on the list of processes to gc the next
13049 * time things are idle.
13050 */
13051 final void scheduleAppGcLocked(ProcessRecord app) {
13052 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013053 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013054 return;
13055 }
13056 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013057 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013058 scheduleAppGcsLocked();
13059 }
13060 }
13061
Dianne Hackborn287952c2010-09-22 22:34:31 -070013062 final void checkExcessivePowerUsageLocked(boolean doKills) {
13063 updateCpuStatsNow();
13064
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013065 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
Dianne Hackborn287952c2010-09-22 22:34:31 -070013066 boolean doWakeKills = doKills;
13067 boolean doCpuKills = doKills;
13068 if (mLastPowerCheckRealtime == 0) {
13069 doWakeKills = false;
13070 }
13071 if (mLastPowerCheckUptime == 0) {
13072 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013073 }
13074 if (stats.isScreenOn()) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070013075 doWakeKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013076 }
13077 final long curRealtime = SystemClock.elapsedRealtime();
Dianne Hackborn287952c2010-09-22 22:34:31 -070013078 final long realtimeSince = curRealtime - mLastPowerCheckRealtime;
13079 final long curUptime = SystemClock.uptimeMillis();
13080 final long uptimeSince = curUptime - mLastPowerCheckUptime;
13081 mLastPowerCheckRealtime = curRealtime;
13082 mLastPowerCheckUptime = curUptime;
13083 if (realtimeSince < WAKE_LOCK_MIN_CHECK_DURATION) {
13084 doWakeKills = false;
13085 }
13086 if (uptimeSince < CPU_MIN_CHECK_DURATION) {
13087 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013088 }
13089 int i = mLruProcesses.size();
13090 while (i > 0) {
13091 i--;
13092 ProcessRecord app = mLruProcesses.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -070013093 if (!app.keeping) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013094 long wtime;
13095 synchronized (stats) {
13096 wtime = stats.getProcessWakeTime(app.info.uid,
13097 app.pid, curRealtime);
13098 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070013099 long wtimeUsed = wtime - app.lastWakeTime;
13100 long cputimeUsed = app.curCpuTime - app.lastCpuTime;
13101 if (DEBUG_POWER) {
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070013102 StringBuilder sb = new StringBuilder(128);
13103 sb.append("Wake for ");
13104 app.toShortString(sb);
13105 sb.append(": over ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070013106 TimeUtils.formatDuration(realtimeSince, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070013107 sb.append(" used ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070013108 TimeUtils.formatDuration(wtimeUsed, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070013109 sb.append(" (");
Dianne Hackborn287952c2010-09-22 22:34:31 -070013110 sb.append((wtimeUsed*100)/realtimeSince);
13111 sb.append("%)");
13112 Slog.i(TAG, sb.toString());
13113 sb.setLength(0);
13114 sb.append("CPU for ");
13115 app.toShortString(sb);
13116 sb.append(": over ");
13117 TimeUtils.formatDuration(uptimeSince, sb);
13118 sb.append(" used ");
13119 TimeUtils.formatDuration(cputimeUsed, sb);
13120 sb.append(" (");
13121 sb.append((cputimeUsed*100)/uptimeSince);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070013122 sb.append("%)");
13123 Slog.i(TAG, sb.toString());
13124 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013125 // If a process has held a wake lock for more
13126 // than 50% of the time during this period,
13127 // that sounds pad. Kill!
Dianne Hackborn287952c2010-09-22 22:34:31 -070013128 if (doWakeKills && realtimeSince > 0
13129 && ((wtimeUsed*100)/realtimeSince) >= 50) {
13130 synchronized (stats) {
13131 stats.reportExcessiveWakeLocked(app.info.uid, app.processName,
13132 realtimeSince, wtimeUsed);
13133 }
13134 Slog.w(TAG, "Excessive wake lock in " + app.processName
13135 + " (pid " + app.pid + "): held " + wtimeUsed
13136 + " during " + realtimeSince);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013137 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13138 app.processName, app.setAdj, "excessive wake lock");
13139 Process.killProcessQuiet(app.pid);
Dianne Hackborn287952c2010-09-22 22:34:31 -070013140 } else if (doCpuKills && uptimeSince > 0
13141 && ((cputimeUsed*100)/uptimeSince) >= 50) {
13142 synchronized (stats) {
13143 stats.reportExcessiveCpuLocked(app.info.uid, app.processName,
13144 uptimeSince, cputimeUsed);
13145 }
13146 Slog.w(TAG, "Excessive CPU in " + app.processName
13147 + " (pid " + app.pid + "): used " + cputimeUsed
13148 + " during " + uptimeSince);
13149 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13150 app.processName, app.setAdj, "excessive cpu");
13151 Process.killProcessQuiet(app.pid);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013152 } else {
13153 app.lastWakeTime = wtime;
Dianne Hackborn287952c2010-09-22 22:34:31 -070013154 app.lastCpuTime = app.curCpuTime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013155 }
13156 }
13157 }
13158 }
13159
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013160 private final void updateOomAdjLocked(
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013161 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013162 app.hiddenAdj = hiddenAdj;
13163
13164 if (app.thread == null) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013165 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013166 }
13167
Dianne Hackborn287952c2010-09-22 22:34:31 -070013168 final boolean wasKeeping = app.keeping;
13169
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013170 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013171
Jeff Brown10e89712011-07-08 18:52:57 -070013172 if (app.curRawAdj != app.setRawAdj) {
13173 if (app.curRawAdj > FOREGROUND_APP_ADJ
13174 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
13175 // If this app is transitioning from foreground to
13176 // non-foreground, have it do a gc.
13177 scheduleAppGcLocked(app);
13178 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
13179 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
13180 // Likewise do a gc when an app is moving in to the
13181 // background (such as a service stopping).
13182 scheduleAppGcLocked(app);
13183 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070013184
Jeff Brown10e89712011-07-08 18:52:57 -070013185 if (wasKeeping && !app.keeping) {
13186 // This app is no longer something we want to keep. Note
13187 // its current wake lock time to later know to kill it if
13188 // it is not behaving well.
13189 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
13190 synchronized (stats) {
13191 app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
13192 app.pid, SystemClock.elapsedRealtime());
13193 }
13194 app.lastCpuTime = app.curCpuTime;
13195 }
13196
13197 app.setRawAdj = app.curRawAdj;
13198 }
13199 if (adj != app.setAdj) {
13200 if (Process.setOomAdj(app.pid, adj)) {
13201 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
13202 TAG, "Set app " + app.processName +
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013203 " oom adj to " + adj + " because " + app.adjType);
Jeff Brown10e89712011-07-08 18:52:57 -070013204 app.setAdj = adj;
13205 } else {
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013206 Slog.w(TAG, "Failed setting oom adj of " + app + " to " + adj);
Jeff Brown10e89712011-07-08 18:52:57 -070013207 }
13208 }
13209 if (app.setSchedGroup != app.curSchedGroup) {
13210 app.setSchedGroup = app.curSchedGroup;
13211 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
13212 "Setting process group of " + app.processName
13213 + " to " + app.curSchedGroup);
13214 if (app.waitingToKill != null &&
13215 app.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {
13216 Slog.i(TAG, "Killing " + app.toShortString() + ": " + app.waitingToKill);
13217 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13218 app.processName, app.setAdj, app.waitingToKill);
13219 Process.killProcessQuiet(app.pid);
13220 } else {
13221 if (true) {
13222 long oldId = Binder.clearCallingIdentity();
13223 try {
13224 Process.setProcessGroup(app.pid, app.curSchedGroup);
13225 } catch (Exception e) {
13226 Slog.w(TAG, "Failed setting process group of " + app.pid
13227 + " to " + app.curSchedGroup);
13228 e.printStackTrace();
13229 } finally {
13230 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013231 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013232 } else {
Jeff Brown10e89712011-07-08 18:52:57 -070013233 if (app.thread != null) {
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013234 try {
Jeff Brown10e89712011-07-08 18:52:57 -070013235 app.thread.setSchedulingGroup(app.curSchedGroup);
13236 } catch (RemoteException e) {
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013237 }
13238 }
13239 }
13240 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013241 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013242 }
13243
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013244 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013245 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013246 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013247 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013248 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013249 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013250 }
13251 }
13252 return resumedActivity;
13253 }
13254
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013255 private final void updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013256 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013257 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
13258 int curAdj = app.curAdj;
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013259 final boolean wasHidden = curAdj >= HIDDEN_APP_MIN_ADJ
13260 && curAdj <= HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013261
13262 mAdjSeq++;
13263
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013264 updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
13265 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
13266 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
13267 if (nowHidden != wasHidden) {
13268 // Changed to/from hidden state, so apps after it in the LRU
13269 // list may also be changed.
13270 updateOomAdjLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013271 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013272 }
13273
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013274 final void updateOomAdjLocked() {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013275 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013276 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
13277
13278 if (false) {
13279 RuntimeException e = new RuntimeException();
13280 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080013281 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013282 }
13283
13284 mAdjSeq++;
13285
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013286 // Let's determine how many processes we have running vs.
13287 // how many slots we have for background processes; we may want
13288 // to put multiple processes in a slot of there are enough of
13289 // them.
13290 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
13291 int factor = (mLruProcesses.size()-4)/numSlots;
13292 if (factor < 1) factor = 1;
13293 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070013294 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013295
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013296 // First update the OOM adjustment for each of the
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013297 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013298 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013299 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013300 int numBg = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013301 while (i > 0) {
13302 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013303 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013304 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013305 updateOomAdjLocked(app, curHiddenAdj, TOP_APP);
13306 if (curHiddenAdj < EMPTY_APP_ADJ
13307 && app.curAdj == curHiddenAdj) {
13308 step++;
13309 if (step >= factor) {
13310 step = 0;
13311 curHiddenAdj++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013312 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013313 }
13314 if (!app.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -070013315 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013316 numHidden++;
13317 if (numHidden > mProcessLimit) {
13318 Slog.i(TAG, "No longer want " + app.processName
13319 + " (pid " + app.pid + "): hidden #" + numHidden);
13320 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13321 app.processName, app.setAdj, "too many background");
13322 app.killedBackground = true;
13323 Process.killProcessQuiet(app.pid);
13324 } else {
13325 numBg++;
Dianne Hackborn8633e682010-04-22 16:03:41 -070013326 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013327 } else if (app.curAdj >= HOME_APP_ADJ) {
13328 numBg++;
Dianne Hackborn8633e682010-04-22 16:03:41 -070013329 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013330 }
13331 }
13332
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013333 // Now determine the memory trimming level of background processes.
13334 // Unfortunately we need to start at the back of the list to do this
13335 // properly. We only do this if the number of background apps we
13336 // are managing to keep around is less than half the maximum we desire;
13337 // if we are keeping a good number around, we'll let them use whatever
13338 // memory they want.
13339 if (numHidden <= (MAX_HIDDEN_APPS/2)) {
13340 final int N = mLruProcesses.size();
13341 factor = numBg/3;
13342 step = 0;
13343 int curLevel = ComponentCallbacks.TRIM_MEMORY_COMPLETE;
13344 for (i=0; i<N; i++) {
13345 ProcessRecord app = mLruProcesses.get(i);
13346 if (app.curAdj >= HIDDEN_APP_MIN_ADJ && !app.killedBackground) {
13347 if (app.trimMemoryLevel < curLevel && app.thread != null) {
13348 try {
13349 app.thread.scheduleTrimMemory(curLevel);
13350 } catch (RemoteException e) {
13351 }
13352 if (curLevel >= ComponentCallbacks.TRIM_MEMORY_COMPLETE) {
13353 // For these apps we will also finish their activities
13354 // to help them free memory.
13355 mMainStack.destroyActivitiesLocked(app, false);
13356 }
13357 }
13358 app.trimMemoryLevel = curLevel;
13359 step++;
13360 if (step >= factor) {
13361 switch (curLevel) {
13362 case ComponentCallbacks.TRIM_MEMORY_COMPLETE:
13363 curLevel = ComponentCallbacks.TRIM_MEMORY_MODERATE;
13364 break;
13365 case ComponentCallbacks.TRIM_MEMORY_MODERATE:
13366 curLevel = ComponentCallbacks.TRIM_MEMORY_BACKGROUND;
13367 break;
13368 }
13369 }
Dianne Hackbornf0754f5b2011-07-21 16:02:07 -070013370 } else if (app.curAdj == HEAVY_WEIGHT_APP_ADJ) {
13371 if (app.trimMemoryLevel < ComponentCallbacks.TRIM_MEMORY_BACKGROUND
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013372 && app.thread != null) {
13373 try {
Dianne Hackbornf0754f5b2011-07-21 16:02:07 -070013374 app.thread.scheduleTrimMemory(ComponentCallbacks.TRIM_MEMORY_BACKGROUND);
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013375 } catch (RemoteException e) {
13376 }
13377 }
Dianne Hackbornf0754f5b2011-07-21 16:02:07 -070013378 app.trimMemoryLevel = ComponentCallbacks.TRIM_MEMORY_BACKGROUND;
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013379 } else {
13380 app.trimMemoryLevel = 0;
13381 }
13382 }
13383 } else {
13384 final int N = mLruProcesses.size();
13385 for (i=0; i<N; i++) {
13386 ProcessRecord app = mLruProcesses.get(i);
13387 app.trimMemoryLevel = 0;
13388 }
13389 }
13390
13391 if (mAlwaysFinishActivities) {
13392 mMainStack.destroyActivitiesLocked(null, false);
13393 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013394 }
13395
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013396 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013397 synchronized (this) {
13398 int i;
13399
13400 // First remove any unused application processes whose package
13401 // has been removed.
13402 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
13403 final ProcessRecord app = mRemovedProcesses.get(i);
13404 if (app.activities.size() == 0
13405 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013406 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013407 TAG, "Exiting empty application process "
13408 + app.processName + " ("
13409 + (app.thread != null ? app.thread.asBinder() : null)
13410 + ")\n");
13411 if (app.pid > 0 && app.pid != MY_PID) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070013412 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13413 app.processName, app.setAdj, "empty");
13414 Process.killProcessQuiet(app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013415 } else {
13416 try {
13417 app.thread.scheduleExit();
13418 } catch (Exception e) {
13419 // Ignore exceptions.
13420 }
13421 }
13422 cleanUpApplicationRecordLocked(app, false, -1);
13423 mRemovedProcesses.remove(i);
13424
13425 if (app.persistent) {
13426 if (app.persistent) {
13427 addAppLocked(app.info);
13428 }
13429 }
13430 }
13431 }
13432
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013433 // Now update the oom adj for all processes.
13434 updateOomAdjLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013435 }
13436 }
13437
13438 /** This method sends the specified signal to each of the persistent apps */
13439 public void signalPersistentProcesses(int sig) throws RemoteException {
13440 if (sig != Process.SIGNAL_USR1) {
13441 throw new SecurityException("Only SIGNAL_USR1 is allowed");
13442 }
13443
13444 synchronized (this) {
13445 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
13446 != PackageManager.PERMISSION_GRANTED) {
13447 throw new SecurityException("Requires permission "
13448 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
13449 }
13450
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013451 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
13452 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013453 if (r.thread != null && r.persistent) {
13454 Process.sendSignal(r.pid, sig);
13455 }
13456 }
13457 }
13458 }
13459
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013460 public boolean profileControl(String process, boolean start,
Romain Guy7eabe552011-07-21 14:56:34 -070013461 String path, ParcelFileDescriptor fd, int profileType) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013462
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013463 try {
13464 synchronized (this) {
13465 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
13466 // its own permission.
13467 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
13468 != PackageManager.PERMISSION_GRANTED) {
13469 throw new SecurityException("Requires permission "
13470 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013471 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013472
13473 if (start && fd == null) {
13474 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013475 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013476
13477 ProcessRecord proc = null;
13478 try {
13479 int pid = Integer.parseInt(process);
13480 synchronized (mPidsSelfLocked) {
13481 proc = mPidsSelfLocked.get(pid);
13482 }
13483 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013484 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013485
13486 if (proc == null) {
13487 HashMap<String, SparseArray<ProcessRecord>> all
13488 = mProcessNames.getMap();
13489 SparseArray<ProcessRecord> procs = all.get(process);
13490 if (procs != null && procs.size() > 0) {
13491 proc = procs.valueAt(0);
13492 }
13493 }
13494
13495 if (proc == null || proc.thread == null) {
13496 throw new IllegalArgumentException("Unknown process: " + process);
13497 }
13498
Dianne Hackbornf02e57b2011-03-01 22:21:04 -080013499 boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
13500 if (!isDebuggable) {
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013501 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
13502 throw new SecurityException("Process not debuggable: " + proc);
13503 }
13504 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013505
Romain Guy7eabe552011-07-21 14:56:34 -070013506 proc.thread.profilerControl(start, path, fd, profileType);
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013507 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013508 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013509 }
13510 } catch (RemoteException e) {
13511 throw new IllegalStateException("Process disappeared");
13512 } finally {
13513 if (fd != null) {
13514 try {
13515 fd.close();
13516 } catch (IOException e) {
13517 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013518 }
13519 }
13520 }
Andy McFadden824c5102010-07-09 16:26:57 -070013521
13522 public boolean dumpHeap(String process, boolean managed,
13523 String path, ParcelFileDescriptor fd) throws RemoteException {
13524
13525 try {
13526 synchronized (this) {
13527 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
13528 // its own permission (same as profileControl).
13529 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
13530 != PackageManager.PERMISSION_GRANTED) {
13531 throw new SecurityException("Requires permission "
13532 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
13533 }
13534
13535 if (fd == null) {
13536 throw new IllegalArgumentException("null fd");
13537 }
13538
13539 ProcessRecord proc = null;
13540 try {
13541 int pid = Integer.parseInt(process);
13542 synchronized (mPidsSelfLocked) {
13543 proc = mPidsSelfLocked.get(pid);
13544 }
13545 } catch (NumberFormatException e) {
13546 }
13547
13548 if (proc == null) {
13549 HashMap<String, SparseArray<ProcessRecord>> all
13550 = mProcessNames.getMap();
13551 SparseArray<ProcessRecord> procs = all.get(process);
13552 if (procs != null && procs.size() > 0) {
13553 proc = procs.valueAt(0);
13554 }
13555 }
13556
13557 if (proc == null || proc.thread == null) {
13558 throw new IllegalArgumentException("Unknown process: " + process);
13559 }
13560
Dianne Hackbornf02e57b2011-03-01 22:21:04 -080013561 boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
13562 if (!isDebuggable) {
Andy McFadden824c5102010-07-09 16:26:57 -070013563 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
13564 throw new SecurityException("Process not debuggable: " + proc);
13565 }
13566 }
13567
13568 proc.thread.dumpHeap(managed, path, fd);
13569 fd = null;
13570 return true;
13571 }
13572 } catch (RemoteException e) {
13573 throw new IllegalStateException("Process disappeared");
13574 } finally {
13575 if (fd != null) {
13576 try {
13577 fd.close();
13578 } catch (IOException e) {
13579 }
13580 }
13581 }
13582 }
13583
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013584 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
13585 public void monitor() {
13586 synchronized (this) { }
13587 }
Svetoslav Ganov54d068e2011-03-02 12:58:40 -080013588
13589 public void onCoreSettingsChange(Bundle settings) {
13590 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
13591 ProcessRecord processRecord = mLruProcesses.get(i);
13592 try {
13593 if (processRecord.thread != null) {
13594 processRecord.thread.setCoreSettings(settings);
13595 }
13596 } catch (RemoteException re) {
13597 /* ignore */
13598 }
13599 }
13600 }
Amith Yamasani4b2e9342011-03-31 12:38:53 -070013601
13602 // Multi-user methods
13603
13604 public boolean switchUser(int userid) {
13605 // TODO
13606 return true;
13607 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013608}