blob: a8fb1ed656401d90c143a8d8946157e8bfc7d68b [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;
2442 if (!updateConfigurationLocked(config, r)) {
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);
3372 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003373 if (doit) {
3374 procs.add(app);
3375 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003376 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
3377 || app.processName.equals(packageName)
3378 || app.processName.startsWith(procNamePrefix)) {
3379 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003380 if (!doit) {
3381 return true;
3382 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003383 app.removed = true;
3384 procs.add(app);
3385 }
3386 }
3387 }
3388 }
3389
3390 int N = procs.size();
3391 for (int i=0; i<N; i++) {
3392 removeProcessLocked(procs.get(i), callerWillRestart);
3393 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003394 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08003395 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003396
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003397 private final boolean forceStopPackageLocked(String name, int uid,
3398 boolean callerWillRestart, boolean purgeCache, boolean doit) {
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07003399 int i;
3400 int N;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003401
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003402 if (uid < 0) {
3403 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003404 uid = AppGlobals.getPackageManager().getPackageUid(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003405 } catch (RemoteException e) {
3406 }
3407 }
3408
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003409 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003410 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003411
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003412 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
3413 while (badApps.hasNext()) {
3414 SparseArray<Long> ba = badApps.next();
3415 if (ba.get(uid) != null) {
3416 badApps.remove();
3417 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003418 }
3419 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003420
3421 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
3422 callerWillRestart, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003423
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003424 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3425 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003426 if (r.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003427 if (!doit) {
3428 return true;
3429 }
3430 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003431 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003432 if (r.app != null) {
3433 r.app.removed = true;
3434 }
3435 r.app = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003436 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003437 }
3438 }
3439
3440 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
3441 for (ServiceRecord service : mServices.values()) {
3442 if (service.packageName.equals(name)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003443 if (!doit) {
3444 return true;
3445 }
3446 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003447 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003448 if (service.app != null) {
3449 service.app.removed = true;
3450 }
3451 service.app = null;
3452 services.add(service);
3453 }
3454 }
3455
3456 N = services.size();
3457 for (i=0; i<N; i++) {
3458 bringDownServiceLocked(services.get(i), true);
3459 }
3460
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003461 if (doit) {
3462 if (purgeCache) {
3463 AttributeCache ac = AttributeCache.instance();
3464 if (ac != null) {
3465 ac.removePackage(name);
3466 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003467 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003468 mMainStack.resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003469 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003470
3471 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003472 }
3473
3474 private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
3475 final String name = app.processName;
3476 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003477 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003478 TAG, "Force removing process " + app + " (" + name
3479 + "/" + uid + ")");
3480
3481 mProcessNames.remove(name, uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003482 if (mHeavyWeightProcess == app) {
3483 mHeavyWeightProcess = null;
3484 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3485 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003486 boolean needRestart = false;
3487 if (app.pid > 0 && app.pid != MY_PID) {
3488 int pid = app.pid;
3489 synchronized (mPidsSelfLocked) {
3490 mPidsSelfLocked.remove(pid);
3491 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3492 }
3493 handleAppDiedLocked(app, true);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003494 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003495 Process.killProcess(pid);
3496
3497 if (app.persistent) {
3498 if (!callerWillRestart) {
3499 addAppLocked(app.info);
3500 } else {
3501 needRestart = true;
3502 }
3503 }
3504 } else {
3505 mRemovedProcesses.add(app);
3506 }
3507
3508 return needRestart;
3509 }
3510
3511 private final void processStartTimedOutLocked(ProcessRecord app) {
3512 final int pid = app.pid;
3513 boolean gone = false;
3514 synchronized (mPidsSelfLocked) {
3515 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
3516 if (knownApp != null && knownApp.thread == null) {
3517 mPidsSelfLocked.remove(pid);
3518 gone = true;
3519 }
3520 }
3521
3522 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003523 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003524 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003525 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003526 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003527 if (mHeavyWeightProcess == app) {
3528 mHeavyWeightProcess = null;
3529 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3530 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003531 // Take care of any launching providers waiting for this process.
3532 checkAppInLaunchingProvidersLocked(app, true);
3533 // Take care of any services that are waiting for the process.
3534 for (int i=0; i<mPendingServices.size(); i++) {
3535 ServiceRecord sr = mPendingServices.get(i);
3536 if (app.info.uid == sr.appInfo.uid
3537 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003538 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003539 mPendingServices.remove(i);
3540 i--;
3541 bringDownServiceLocked(sr, true);
3542 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003543 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07003544 EventLog.writeEvent(EventLogTags.AM_KILL, pid,
3545 app.processName, app.setAdj, "start timeout");
3546 Process.killProcessQuiet(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07003547 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003548 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07003549 try {
3550 IBackupManager bm = IBackupManager.Stub.asInterface(
3551 ServiceManager.getService(Context.BACKUP_SERVICE));
3552 bm.agentDisconnected(app.info.packageName);
3553 } catch (RemoteException e) {
3554 // Can't happen; the backup manager is local
3555 }
3556 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003557 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003558 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003559 mPendingBroadcast.state = BroadcastRecord.IDLE;
3560 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003561 mPendingBroadcast = null;
3562 scheduleBroadcastsLocked();
3563 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003564 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003565 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003566 }
3567 }
3568
3569 private final boolean attachApplicationLocked(IApplicationThread thread,
3570 int pid) {
3571
3572 // Find the application record that is being attached... either via
3573 // the pid if we are running in multiple processes, or just pull the
3574 // next app record if we are emulating process with anonymous threads.
3575 ProcessRecord app;
3576 if (pid != MY_PID && pid >= 0) {
3577 synchronized (mPidsSelfLocked) {
3578 app = mPidsSelfLocked.get(pid);
3579 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003580 } else {
3581 app = null;
3582 }
3583
3584 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003585 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003586 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003587 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003588 if (pid > 0 && pid != MY_PID) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07003589 Process.killProcessQuiet(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003590 } else {
3591 try {
3592 thread.scheduleExit();
3593 } catch (Exception e) {
3594 // Ignore exceptions.
3595 }
3596 }
3597 return false;
3598 }
3599
3600 // If this application record is still attached to a previous
3601 // process, clean it up now.
3602 if (app.thread != null) {
3603 handleAppDiedLocked(app, true);
3604 }
3605
3606 // Tell the process all about itself.
3607
Joe Onorato8a9b2202010-02-26 18:56:32 -08003608 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003609 TAG, "Binding process pid " + pid + " to record " + app);
3610
3611 String processName = app.processName;
3612 try {
3613 thread.asBinder().linkToDeath(new AppDeathRecipient(
3614 app, pid, thread), 0);
3615 } catch (RemoteException e) {
3616 app.resetPackageList();
3617 startProcessLocked(app, "link fail", processName);
3618 return false;
3619 }
3620
Doug Zongker2bec3d42009-12-04 12:52:44 -08003621 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003622
3623 app.thread = thread;
3624 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08003625 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
3626 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003627 app.forcingToForeground = null;
3628 app.foregroundServices = false;
3629 app.debugging = false;
3630
3631 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3632
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003633 boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003634 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003635
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003636 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003637 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003638 }
3639
Joe Onorato8a9b2202010-02-26 18:56:32 -08003640 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003641 TAG, "New app record " + app
3642 + " thread=" + thread.asBinder() + " pid=" + pid);
3643 try {
3644 int testMode = IApplicationThread.DEBUG_OFF;
3645 if (mDebugApp != null && mDebugApp.equals(processName)) {
3646 testMode = mWaitForDebugger
3647 ? IApplicationThread.DEBUG_WAIT
3648 : IApplicationThread.DEBUG_ON;
3649 app.debugging = true;
3650 if (mDebugTransient) {
3651 mDebugApp = mOrigDebugApp;
3652 mWaitForDebugger = mOrigWaitForDebugger;
3653 }
3654 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003655
Christopher Tate181fafa2009-05-14 11:12:14 -07003656 // If the app is being launched for restore or full backup, set it up specially
3657 boolean isRestrictedBackupMode = false;
3658 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
3659 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
Christopher Tate75a99702011-05-18 16:28:19 -07003660 || (mBackupTarget.backupMode == BackupRecord.RESTORE_FULL)
Christopher Tate181fafa2009-05-14 11:12:14 -07003661 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
3662 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003663
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07003664 ensurePackageDexOpt(app.instrumentationInfo != null
3665 ? app.instrumentationInfo.packageName
3666 : app.info.packageName);
3667 if (app.instrumentationClass != null) {
3668 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003669 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003670 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003671 + processName + " with config " + mConfiguration);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04003672 ApplicationInfo appInfo = app.instrumentationInfo != null
3673 ? app.instrumentationInfo : app.info;
Dianne Hackborn8ea5e1d2011-05-27 16:45:31 -07003674 app.compat = compatibilityInfoForPackageLocked(appInfo);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04003675 thread.bindApplication(processName, appInfo, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003676 app.instrumentationClass, app.instrumentationProfileFile,
3677 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003678 isRestrictedBackupMode || !normalMode,
Dianne Hackborn8ea5e1d2011-05-27 16:45:31 -07003679 mConfiguration, app.compat, getCommonServicesLocked(),
Svetoslav Ganov54d068e2011-03-02 12:58:40 -08003680 mCoreSettingsObserver.getCoreSettingsLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003681 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003682 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003683 } catch (Exception e) {
3684 // todo: Yikes! What should we do? For now we will try to
3685 // start another process, but that could easily get us in
3686 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08003687 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003688
3689 app.resetPackageList();
3690 startProcessLocked(app, "bind fail", processName);
3691 return false;
3692 }
3693
3694 // Remove this record from the list of starting applications.
3695 mPersistentStartingProcesses.remove(app);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003696 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
3697 "Attach application locked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003698 mProcessesOnHold.remove(app);
3699
3700 boolean badApp = false;
3701 boolean didSomething = false;
3702
3703 // See if the top visible activity is waiting to run in this process...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003704 ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07003705 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003706 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
3707 && processName.equals(hr.processName)) {
3708 try {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003709 if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003710 didSomething = true;
3711 }
3712 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003713 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003714 + hr.intent.getComponent().flattenToShortString(), e);
3715 badApp = true;
3716 }
3717 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003718 mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003719 }
3720 }
3721
3722 // Find any services that should be running in this process...
3723 if (!badApp && mPendingServices.size() > 0) {
3724 ServiceRecord sr = null;
3725 try {
3726 for (int i=0; i<mPendingServices.size(); i++) {
3727 sr = mPendingServices.get(i);
3728 if (app.info.uid != sr.appInfo.uid
3729 || !processName.equals(sr.processName)) {
3730 continue;
3731 }
3732
3733 mPendingServices.remove(i);
3734 i--;
3735 realStartServiceLocked(sr, app);
3736 didSomething = true;
3737 }
3738 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003739 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003740 + sr.shortName, e);
3741 badApp = true;
3742 }
3743 }
3744
3745 // Check if the next broadcast receiver is in this process...
3746 BroadcastRecord br = mPendingBroadcast;
3747 if (!badApp && br != null && br.curApp == app) {
3748 try {
3749 mPendingBroadcast = null;
3750 processCurBroadcastLocked(br, app);
3751 didSomething = true;
3752 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003753 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003754 + br.curComponent.flattenToShortString(), e);
3755 badApp = true;
Jeff Brown4d94a762010-09-23 11:33:28 -07003756 logBroadcastReceiverDiscardLocked(br);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003757 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
3758 br.resultExtras, br.resultAbort, true);
3759 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01003760 // We need to reset the state if we fails to start the receiver.
3761 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003762 }
3763 }
3764
Christopher Tate181fafa2009-05-14 11:12:14 -07003765 // Check whether the next backup agent is in this process...
3766 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003767 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003768 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07003769 try {
Dianne Hackborne2515ee2011-04-27 18:52:56 -04003770 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo,
3771 compatibilityInfoForPackageLocked(mBackupTarget.appInfo),
3772 mBackupTarget.backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -07003773 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003774 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07003775 e.printStackTrace();
3776 }
3777 }
3778
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003779 if (badApp) {
3780 // todo: Also need to kill application to deal with all
3781 // kinds of exceptions.
3782 handleAppDiedLocked(app, false);
3783 return false;
3784 }
3785
3786 if (!didSomething) {
3787 updateOomAdjLocked();
3788 }
3789
3790 return true;
3791 }
3792
3793 public final void attachApplication(IApplicationThread thread) {
3794 synchronized (this) {
3795 int callingPid = Binder.getCallingPid();
3796 final long origId = Binder.clearCallingIdentity();
3797 attachApplicationLocked(thread, callingPid);
3798 Binder.restoreCallingIdentity(origId);
3799 }
3800 }
3801
Dianne Hackborne88846e2009-09-30 21:34:25 -07003802 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003803 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003804 mMainStack.activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003805 Binder.restoreCallingIdentity(origId);
3806 }
3807
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003808 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003809 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003810 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003811 mWindowManager.enableScreenAfterBoot();
3812 }
3813
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003814 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003815 IntentFilter pkgFilter = new IntentFilter();
3816 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
3817 pkgFilter.addDataScheme("package");
3818 mContext.registerReceiver(new BroadcastReceiver() {
3819 @Override
3820 public void onReceive(Context context, Intent intent) {
3821 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
3822 if (pkgs != null) {
3823 for (String pkg : pkgs) {
Vairavan Srinivasan61f07652010-07-22 13:36:40 -07003824 synchronized (ActivityManagerService.this) {
3825 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
3826 setResultCode(Activity.RESULT_OK);
3827 return;
3828 }
3829 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003830 }
3831 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003832 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003833 }, pkgFilter);
3834
3835 synchronized (this) {
3836 // Ensure that any processes we had put on hold are now started
3837 // up.
3838 final int NP = mProcessesOnHold.size();
3839 if (NP > 0) {
3840 ArrayList<ProcessRecord> procs =
3841 new ArrayList<ProcessRecord>(mProcessesOnHold);
3842 for (int ip=0; ip<NP; ip++) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003843 if (DEBUG_PROCESSES) Slog.v(TAG, "Starting process on hold: "
3844 + procs.get(ip));
3845 startProcessLocked(procs.get(ip), "on-hold", null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003846 }
3847 }
3848
3849 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07003850 // Start looking for apps that are abusing wake locks.
3851 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07003852 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003853 // Tell anyone interested that we are done booting!
Dianne Hackbornf4c454b2010-08-11 12:47:41 -07003854 SystemProperties.set("sys.boot_completed", "1");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003855 broadcastIntentLocked(null, null,
3856 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
3857 null, null, 0, null, null,
3858 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
3859 false, false, MY_PID, Process.SYSTEM_UID);
3860 }
3861 }
3862 }
3863
3864 final void ensureBootCompleted() {
3865 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003866 boolean enableScreen;
3867 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003868 booting = mBooting;
3869 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003870 enableScreen = !mBooted;
3871 mBooted = true;
3872 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003873
3874 if (booting) {
3875 finishBooting();
3876 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003877
3878 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003879 enableScreenAfterBoot();
3880 }
3881 }
3882
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08003883 public final void activityPaused(IBinder token) {
3884 final long origId = Binder.clearCallingIdentity();
3885 mMainStack.activityPaused(token, false);
3886 Binder.restoreCallingIdentity(origId);
3887 }
3888
3889 public final void activityStopped(IBinder token, Bundle icicle, Bitmap thumbnail,
3890 CharSequence description) {
3891 if (localLOGV) Slog.v(
3892 TAG, "Activity stopped: token=" + token);
3893
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003894 // Refuse possible leaked file descriptors
3895 if (icicle != null && icicle.hasFileDescriptors()) {
3896 throw new IllegalArgumentException("File descriptors passed in Bundle");
3897 }
3898
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003899 ActivityRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003900
3901 final long origId = Binder.clearCallingIdentity();
3902
3903 synchronized (this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07003904 r = mMainStack.isInStackLocked(token);
3905 if (r != null) {
3906 r.stack.activityStoppedLocked(r, icicle, thumbnail, description);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003907 }
3908 }
3909
3910 if (r != null) {
3911 sendPendingThumbnail(r, null, null, null, false);
3912 }
3913
3914 trimApplications();
3915
3916 Binder.restoreCallingIdentity(origId);
3917 }
3918
3919 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003920 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003921 mMainStack.activityDestroyed(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003922 }
3923
3924 public String getCallingPackage(IBinder token) {
3925 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003926 ActivityRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07003927 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003928 }
3929 }
3930
3931 public ComponentName getCallingActivity(IBinder token) {
3932 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003933 ActivityRecord r = getCallingRecordLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003934 return r != null ? r.intent.getComponent() : null;
3935 }
3936 }
3937
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003938 private ActivityRecord getCallingRecordLocked(IBinder token) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07003939 ActivityRecord r = mMainStack.isInStackLocked(token);
3940 if (r == null) {
3941 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003942 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -07003943 return r.resultTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003944 }
3945
3946 public ComponentName getActivityClassForToken(IBinder token) {
3947 synchronized(this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07003948 ActivityRecord r = mMainStack.isInStackLocked(token);
3949 if (r == null) {
3950 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003951 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -07003952 return r.intent.getComponent();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003953 }
3954 }
3955
3956 public String getPackageForToken(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.packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003963 }
3964 }
3965
3966 public IIntentSender getIntentSender(int type,
3967 String packageName, IBinder token, String resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003968 int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003969 // Refuse possible leaked file descriptors
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003970 if (intents != null) {
3971 if (intents.length < 1) {
3972 throw new IllegalArgumentException("Intents array length must be >= 1");
3973 }
3974 for (int i=0; i<intents.length; i++) {
3975 Intent intent = intents[i];
Dianne Hackborn52b0ce02011-04-14 13:09:32 -07003976 if (intent != null) {
3977 if (intent.hasFileDescriptors()) {
3978 throw new IllegalArgumentException("File descriptors passed in Intent");
3979 }
3980 if (type == INTENT_SENDER_BROADCAST &&
3981 (intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
3982 throw new IllegalArgumentException(
3983 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
3984 }
3985 intents[i] = new Intent(intent);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003986 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003987 }
3988 if (resolvedTypes != null && resolvedTypes.length != intents.length) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003989 throw new IllegalArgumentException(
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003990 "Intent array length does not match resolvedTypes length");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003991 }
3992 }
3993
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003994 synchronized(this) {
3995 int callingUid = Binder.getCallingUid();
3996 try {
Jeff Brown10e89712011-07-08 18:52:57 -07003997 if (callingUid != 0 && callingUid != Process.SYSTEM_UID) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003998 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003999 .getPackageUid(packageName);
4000 if (uid != Binder.getCallingUid()) {
4001 String msg = "Permission Denial: getIntentSender() from pid="
4002 + Binder.getCallingPid()
4003 + ", uid=" + Binder.getCallingUid()
4004 + ", (need uid=" + uid + ")"
4005 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004006 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004007 throw new SecurityException(msg);
4008 }
4009 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004010
4011 return getIntentSenderLocked(type, packageName, callingUid,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004012 token, resultWho, requestCode, intents, resolvedTypes, flags);
Dianne Hackborn860755f2010-06-03 18:47:52 -07004013
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004014 } catch (RemoteException e) {
4015 throw new SecurityException(e);
4016 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004017 }
4018 }
4019
4020 IIntentSender getIntentSenderLocked(int type,
4021 String packageName, int callingUid, IBinder token, String resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004022 int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004023 ActivityRecord activity = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004024 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004025 activity = mMainStack.isInStackLocked(token);
4026 if (activity == null) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07004027 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004028 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004029 if (activity.finishing) {
4030 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004031 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004032 }
4033
4034 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
4035 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
4036 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
4037 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
4038 |PendingIntent.FLAG_UPDATE_CURRENT);
4039
4040 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
4041 type, packageName, activity, resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004042 requestCode, intents, resolvedTypes, flags);
Dianne Hackborn860755f2010-06-03 18:47:52 -07004043 WeakReference<PendingIntentRecord> ref;
4044 ref = mIntentSenderRecords.get(key);
4045 PendingIntentRecord rec = ref != null ? ref.get() : null;
4046 if (rec != null) {
4047 if (!cancelCurrent) {
4048 if (updateCurrent) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004049 if (rec.key.requestIntent != null) {
4050 rec.key.requestIntent.replaceExtras(intents != null ? intents[0] : null);
4051 }
4052 if (intents != null) {
4053 intents[intents.length-1] = rec.key.requestIntent;
4054 rec.key.allIntents = intents;
4055 rec.key.allResolvedTypes = resolvedTypes;
4056 } else {
4057 rec.key.allIntents = null;
4058 rec.key.allResolvedTypes = null;
4059 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004060 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004061 return rec;
4062 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004063 rec.canceled = true;
4064 mIntentSenderRecords.remove(key);
4065 }
4066 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004067 return rec;
4068 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004069 rec = new PendingIntentRecord(this, key, callingUid);
4070 mIntentSenderRecords.put(key, rec.ref);
4071 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
4072 if (activity.pendingResults == null) {
4073 activity.pendingResults
4074 = new HashSet<WeakReference<PendingIntentRecord>>();
4075 }
4076 activity.pendingResults.add(rec.ref);
4077 }
4078 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004079 }
4080
4081 public void cancelIntentSender(IIntentSender sender) {
4082 if (!(sender instanceof PendingIntentRecord)) {
4083 return;
4084 }
4085 synchronized(this) {
4086 PendingIntentRecord rec = (PendingIntentRecord)sender;
4087 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004088 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004089 .getPackageUid(rec.key.packageName);
4090 if (uid != Binder.getCallingUid()) {
4091 String msg = "Permission Denial: cancelIntentSender() from pid="
4092 + Binder.getCallingPid()
4093 + ", uid=" + Binder.getCallingUid()
4094 + " is not allowed to cancel packges "
4095 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004096 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004097 throw new SecurityException(msg);
4098 }
4099 } catch (RemoteException e) {
4100 throw new SecurityException(e);
4101 }
4102 cancelIntentSenderLocked(rec, true);
4103 }
4104 }
4105
4106 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
4107 rec.canceled = true;
4108 mIntentSenderRecords.remove(rec.key);
4109 if (cleanActivity && rec.key.activity != null) {
4110 rec.key.activity.pendingResults.remove(rec.ref);
4111 }
4112 }
4113
4114 public String getPackageForIntentSender(IIntentSender pendingResult) {
4115 if (!(pendingResult instanceof PendingIntentRecord)) {
4116 return null;
4117 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07004118 try {
4119 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
4120 return res.key.packageName;
4121 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004122 }
4123 return null;
4124 }
4125
Dianne Hackborn6c418d52011-06-29 14:05:33 -07004126 public boolean isIntentSenderTargetedToPackage(IIntentSender pendingResult) {
4127 if (!(pendingResult instanceof PendingIntentRecord)) {
4128 return false;
4129 }
4130 try {
4131 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
4132 if (res.key.allIntents == null) {
4133 return false;
4134 }
4135 for (int i=0; i<res.key.allIntents.length; i++) {
4136 Intent intent = res.key.allIntents[i];
4137 if (intent.getPackage() != null && intent.getComponent() != null) {
4138 return false;
4139 }
4140 }
4141 return true;
4142 } catch (ClassCastException e) {
4143 }
4144 return false;
4145 }
4146
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004147 public void setProcessLimit(int max) {
4148 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4149 "setProcessLimit()");
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004150 synchronized (this) {
4151 mProcessLimit = max < 0 ? MAX_HIDDEN_APPS : max;
4152 mProcessLimitOverride = max;
4153 }
4154 trimApplications();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004155 }
4156
4157 public int getProcessLimit() {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004158 synchronized (this) {
4159 return mProcessLimitOverride;
4160 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004161 }
4162
4163 void foregroundTokenDied(ForegroundToken token) {
4164 synchronized (ActivityManagerService.this) {
4165 synchronized (mPidsSelfLocked) {
4166 ForegroundToken cur
4167 = mForegroundProcesses.get(token.pid);
4168 if (cur != token) {
4169 return;
4170 }
4171 mForegroundProcesses.remove(token.pid);
4172 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
4173 if (pr == null) {
4174 return;
4175 }
4176 pr.forcingToForeground = null;
4177 pr.foregroundServices = false;
4178 }
4179 updateOomAdjLocked();
4180 }
4181 }
4182
4183 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
4184 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4185 "setProcessForeground()");
4186 synchronized(this) {
4187 boolean changed = false;
4188
4189 synchronized (mPidsSelfLocked) {
4190 ProcessRecord pr = mPidsSelfLocked.get(pid);
4191 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004192 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004193 return;
4194 }
4195 ForegroundToken oldToken = mForegroundProcesses.get(pid);
4196 if (oldToken != null) {
4197 oldToken.token.unlinkToDeath(oldToken, 0);
4198 mForegroundProcesses.remove(pid);
4199 pr.forcingToForeground = null;
4200 changed = true;
4201 }
4202 if (isForeground && token != null) {
4203 ForegroundToken newToken = new ForegroundToken() {
4204 public void binderDied() {
4205 foregroundTokenDied(this);
4206 }
4207 };
4208 newToken.pid = pid;
4209 newToken.token = token;
4210 try {
4211 token.linkToDeath(newToken, 0);
4212 mForegroundProcesses.put(pid, newToken);
4213 pr.forcingToForeground = token;
4214 changed = true;
4215 } catch (RemoteException e) {
4216 // If the process died while doing this, we will later
4217 // do the cleanup with the process death link.
4218 }
4219 }
4220 }
4221
4222 if (changed) {
4223 updateOomAdjLocked();
4224 }
4225 }
4226 }
4227
4228 // =========================================================
4229 // PERMISSIONS
4230 // =========================================================
4231
4232 static class PermissionController extends IPermissionController.Stub {
4233 ActivityManagerService mActivityManagerService;
4234 PermissionController(ActivityManagerService activityManagerService) {
4235 mActivityManagerService = activityManagerService;
4236 }
4237
4238 public boolean checkPermission(String permission, int pid, int uid) {
4239 return mActivityManagerService.checkPermission(permission, pid,
4240 uid) == PackageManager.PERMISSION_GRANTED;
4241 }
4242 }
4243
4244 /**
4245 * This can be called with or without the global lock held.
4246 */
4247 int checkComponentPermission(String permission, int pid, int uid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004248 int owningUid, boolean exported) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004249 // We might be performing an operation on behalf of an indirect binder
4250 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
4251 // client identity accordingly before proceeding.
4252 Identity tlsIdentity = sCallerIdentity.get();
4253 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004254 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004255 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
4256 uid = tlsIdentity.uid;
4257 pid = tlsIdentity.pid;
4258 }
4259
4260 // Root, system server and our own process get to do everything.
Jeff Brown10e89712011-07-08 18:52:57 -07004261 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004262 return PackageManager.PERMISSION_GRANTED;
4263 }
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004264 // If there is a uid that owns whatever is being accessed, it has
4265 // blanket access to it regardless of the permissions it requires.
4266 if (owningUid >= 0 && uid == owningUid) {
4267 return PackageManager.PERMISSION_GRANTED;
4268 }
4269 // If the target is not exported, then nobody else can get to it.
4270 if (!exported) {
4271 Slog.w(TAG, "Permission denied: checkComponentPermission() owningUid=" + owningUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004272 return PackageManager.PERMISSION_DENIED;
4273 }
4274 if (permission == null) {
4275 return PackageManager.PERMISSION_GRANTED;
4276 }
4277 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004278 return AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004279 .checkUidPermission(permission, uid);
4280 } catch (RemoteException e) {
4281 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004282 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004283 }
4284 return PackageManager.PERMISSION_DENIED;
4285 }
4286
4287 /**
4288 * As the only public entry point for permissions checking, this method
4289 * can enforce the semantic that requesting a check on a null global
4290 * permission is automatically denied. (Internally a null permission
4291 * string is used when calling {@link #checkComponentPermission} in cases
4292 * when only uid-based security is needed.)
4293 *
4294 * This can be called with or without the global lock held.
4295 */
4296 public int checkPermission(String permission, int pid, int uid) {
4297 if (permission == null) {
4298 return PackageManager.PERMISSION_DENIED;
4299 }
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004300 return checkComponentPermission(permission, pid, uid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004301 }
4302
4303 /**
4304 * Binder IPC calls go through the public entry point.
4305 * This can be called with or without the global lock held.
4306 */
4307 int checkCallingPermission(String permission) {
4308 return checkPermission(permission,
4309 Binder.getCallingPid(),
4310 Binder.getCallingUid());
4311 }
4312
4313 /**
4314 * This can be called with or without the global lock held.
4315 */
4316 void enforceCallingPermission(String permission, String func) {
4317 if (checkCallingPermission(permission)
4318 == PackageManager.PERMISSION_GRANTED) {
4319 return;
4320 }
4321
4322 String msg = "Permission Denial: " + func + " from pid="
4323 + Binder.getCallingPid()
4324 + ", uid=" + Binder.getCallingUid()
4325 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004326 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004327 throw new SecurityException(msg);
4328 }
4329
4330 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
Dianne Hackborn48058e82010-09-27 16:53:23 -07004331 ProviderInfo pi, Uri uri, int uid, int modeFlags) {
4332 boolean readPerm = (modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0;
4333 boolean writePerm = (modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0;
4334 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4335 "checkHoldingPermissionsLocked: uri=" + uri + " uid=" + uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004336 try {
Dianne Hackborn48058e82010-09-27 16:53:23 -07004337 // Is the component private from the target uid?
4338 final boolean prv = !pi.exported && pi.applicationInfo.uid != uid;
4339
4340 // Acceptable if the there is no read permission needed from the
4341 // target or the target is holding the read permission.
4342 if (!readPerm) {
4343 if ((!prv && pi.readPermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004344 (pm.checkUidPermission(pi.readPermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004345 == PackageManager.PERMISSION_GRANTED)) {
4346 readPerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004347 }
4348 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004349
4350 // Acceptable if the there is no write permission needed from the
4351 // target or the target is holding the read permission.
4352 if (!writePerm) {
4353 if (!prv && (pi.writePermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004354 (pm.checkUidPermission(pi.writePermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004355 == PackageManager.PERMISSION_GRANTED)) {
4356 writePerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004357 }
4358 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004359
4360 // Acceptable if there is a path permission matching the URI that
4361 // the target holds the permission on.
4362 PathPermission[] pps = pi.pathPermissions;
4363 if (pps != null && (!readPerm || !writePerm)) {
4364 final String path = uri.getPath();
4365 int i = pps.length;
4366 while (i > 0 && (!readPerm || !writePerm)) {
4367 i--;
4368 PathPermission pp = pps[i];
4369 if (!readPerm) {
4370 final String pprperm = pp.getReadPermission();
4371 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking read perm for "
4372 + pprperm + " for " + pp.getPath()
4373 + ": match=" + pp.match(path)
4374 + " check=" + pm.checkUidPermission(pprperm, uid));
4375 if (pprperm != null && pp.match(path) &&
4376 (pm.checkUidPermission(pprperm, uid)
4377 == PackageManager.PERMISSION_GRANTED)) {
4378 readPerm = true;
4379 }
4380 }
4381 if (!writePerm) {
4382 final String ppwperm = pp.getWritePermission();
4383 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking write perm "
4384 + ppwperm + " for " + pp.getPath()
4385 + ": match=" + pp.match(path)
4386 + " check=" + pm.checkUidPermission(ppwperm, uid));
4387 if (ppwperm != null && pp.match(path) &&
4388 (pm.checkUidPermission(ppwperm, uid)
4389 == PackageManager.PERMISSION_GRANTED)) {
4390 writePerm = true;
4391 }
4392 }
4393 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004394 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004395 } catch (RemoteException e) {
4396 return false;
4397 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004398
4399 return readPerm && writePerm;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004400 }
4401
4402 private final boolean checkUriPermissionLocked(Uri uri, int uid,
4403 int modeFlags) {
4404 // Root gets to do everything.
Jeff Brown10e89712011-07-08 18:52:57 -07004405 if (uid == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004406 return true;
4407 }
4408 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
4409 if (perms == null) return false;
4410 UriPermission perm = perms.get(uri);
4411 if (perm == null) return false;
4412 return (modeFlags&perm.modeFlags) == modeFlags;
4413 }
4414
4415 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
4416 // Another redirected-binder-call permissions check as in
4417 // {@link checkComponentPermission}.
4418 Identity tlsIdentity = sCallerIdentity.get();
4419 if (tlsIdentity != null) {
4420 uid = tlsIdentity.uid;
4421 pid = tlsIdentity.pid;
4422 }
4423
4424 // Our own process gets to do everything.
4425 if (pid == MY_PID) {
4426 return PackageManager.PERMISSION_GRANTED;
4427 }
4428 synchronized(this) {
4429 return checkUriPermissionLocked(uri, uid, modeFlags)
4430 ? PackageManager.PERMISSION_GRANTED
4431 : PackageManager.PERMISSION_DENIED;
4432 }
4433 }
4434
Dianne Hackborn39792d22010-08-19 18:01:52 -07004435 /**
4436 * Check if the targetPkg can be granted permission to access uri by
4437 * the callingUid using the given modeFlags. Throws a security exception
4438 * if callingUid is not allowed to do this. Returns the uid of the target
4439 * if the URI permission grant should be performed; returns -1 if it is not
4440 * needed (for example targetPkg already has permission to access the URI).
4441 */
4442 int checkGrantUriPermissionLocked(int callingUid, String targetPkg,
4443 Uri uri, int modeFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004444 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4445 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4446 if (modeFlags == 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004447 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004448 }
4449
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004450 if (targetPkg != null) {
4451 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4452 "Checking grant " + targetPkg + " permission to " + uri);
4453 }
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004454
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004455 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004456
4457 // If this is not a content: uri, we can't do anything with it.
4458 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004459 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004460 "Can't grant URI permission for non-content URI: " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004461 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004462 }
4463
4464 String name = uri.getAuthority();
4465 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004466 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004467 if (cpr != null) {
4468 pi = cpr.info;
4469 } else {
4470 try {
4471 pi = pm.resolveContentProvider(name,
4472 PackageManager.GET_URI_PERMISSION_PATTERNS);
4473 } catch (RemoteException ex) {
4474 }
4475 }
4476 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004477 Slog.w(TAG, "No content provider found for: " + name);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004478 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004479 }
4480
4481 int targetUid;
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004482 if (targetPkg != null) {
4483 try {
4484 targetUid = pm.getPackageUid(targetPkg);
4485 if (targetUid < 0) {
4486 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4487 "Can't grant URI permission no uid for: " + targetPkg);
4488 return -1;
4489 }
4490 } catch (RemoteException ex) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004491 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004492 }
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004493 } else {
4494 targetUid = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004495 }
4496
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004497 if (targetUid >= 0) {
4498 // First... does the target actually need this permission?
4499 if (checkHoldingPermissionsLocked(pm, pi, uri, targetUid, modeFlags)) {
4500 // No need to grant the target this permission.
4501 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4502 "Target " + targetPkg + " already has full permission to " + uri);
4503 return -1;
4504 }
4505 } else {
4506 // First... there is no target package, so can anyone access it?
4507 boolean allowed = pi.exported;
4508 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4509 if (pi.readPermission != null) {
4510 allowed = false;
4511 }
4512 }
4513 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4514 if (pi.writePermission != null) {
4515 allowed = false;
4516 }
4517 }
4518 if (allowed) {
4519 return -1;
4520 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004521 }
4522
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004523 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004524 if (!pi.grantUriPermissions) {
4525 throw new SecurityException("Provider " + pi.packageName
4526 + "/" + pi.name
4527 + " does not allow granting of Uri permissions (uri "
4528 + uri + ")");
4529 }
4530 if (pi.uriPermissionPatterns != null) {
4531 final int N = pi.uriPermissionPatterns.length;
4532 boolean allowed = false;
4533 for (int i=0; i<N; i++) {
4534 if (pi.uriPermissionPatterns[i] != null
4535 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
4536 allowed = true;
4537 break;
4538 }
4539 }
4540 if (!allowed) {
4541 throw new SecurityException("Provider " + pi.packageName
4542 + "/" + pi.name
4543 + " does not allow granting of permission to path of Uri "
4544 + uri);
4545 }
4546 }
4547
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004548 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004549 // this uri?
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004550 if (callingUid != Process.myUid()) {
4551 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
4552 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4553 throw new SecurityException("Uid " + callingUid
4554 + " does not have permission to uri " + uri);
4555 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004556 }
4557 }
4558
Dianne Hackborn39792d22010-08-19 18:01:52 -07004559 return targetUid;
4560 }
4561
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004562 public int checkGrantUriPermission(int callingUid, String targetPkg,
4563 Uri uri, int modeFlags) {
4564 synchronized(this) {
4565 return checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4566 }
4567 }
4568
Dianne Hackborn39792d22010-08-19 18:01:52 -07004569 void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg,
4570 Uri uri, int modeFlags, UriPermissionOwner owner) {
4571 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4572 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4573 if (modeFlags == 0) {
4574 return;
4575 }
4576
4577 // So here we are: the caller has the assumed permission
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004578 // to the uri, and the target doesn't. Let's now give this to
4579 // the target.
4580
Joe Onorato8a9b2202010-02-26 18:56:32 -08004581 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004582 "Granting " + targetPkg + "/" + targetUid + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004583
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004584 HashMap<Uri, UriPermission> targetUris
4585 = mGrantedUriPermissions.get(targetUid);
4586 if (targetUris == null) {
4587 targetUris = new HashMap<Uri, UriPermission>();
4588 mGrantedUriPermissions.put(targetUid, targetUris);
4589 }
4590
4591 UriPermission perm = targetUris.get(uri);
4592 if (perm == null) {
4593 perm = new UriPermission(targetUid, uri);
4594 targetUris.put(uri, perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004595 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004596
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004597 perm.modeFlags |= modeFlags;
Dianne Hackborn39792d22010-08-19 18:01:52 -07004598 if (owner == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004599 perm.globalModeFlags |= modeFlags;
Vairavan Srinivasan91c12c22011-01-21 18:26:06 -08004600 } else {
4601 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4602 perm.readOwners.add(owner);
4603 owner.addReadPermission(perm);
4604 }
4605 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4606 perm.writeOwners.add(owner);
4607 owner.addWritePermission(perm);
4608 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004609 }
4610 }
4611
Dianne Hackborn39792d22010-08-19 18:01:52 -07004612 void grantUriPermissionLocked(int callingUid,
4613 String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) {
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004614 if (targetPkg == null) {
4615 throw new NullPointerException("targetPkg");
4616 }
4617
Dianne Hackborn39792d22010-08-19 18:01:52 -07004618 int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4619 if (targetUid < 0) {
4620 return;
4621 }
4622
4623 grantUriPermissionUncheckedLocked(targetUid, targetPkg, uri, modeFlags, owner);
4624 }
4625
4626 /**
4627 * Like checkGrantUriPermissionLocked, but takes an Intent.
4628 */
4629 int checkGrantUriPermissionFromIntentLocked(int callingUid,
4630 String targetPkg, Intent intent) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07004631 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004632 "Checking URI perm to " + (intent != null ? intent.getData() : null)
Dianne Hackbornb424b632010-08-18 15:59:05 -07004633 + " from " + intent + "; flags=0x"
4634 + Integer.toHexString(intent != null ? intent.getFlags() : 0));
4635
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004636 if (targetPkg == null) {
4637 throw new NullPointerException("targetPkg");
4638 }
4639
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004640 if (intent == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004641 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004642 }
4643 Uri data = intent.getData();
4644 if (data == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004645 return -1;
4646 }
4647 return checkGrantUriPermissionLocked(callingUid, targetPkg, data,
4648 intent.getFlags());
4649 }
4650
4651 /**
4652 * Like grantUriPermissionUncheckedLocked, but takes an Intent.
4653 */
4654 void grantUriPermissionUncheckedFromIntentLocked(int targetUid,
4655 String targetPkg, Intent intent, UriPermissionOwner owner) {
4656 grantUriPermissionUncheckedLocked(targetUid, targetPkg, intent.getData(),
4657 intent.getFlags(), owner);
4658 }
4659
4660 void grantUriPermissionFromIntentLocked(int callingUid,
4661 String targetPkg, Intent intent, UriPermissionOwner owner) {
4662 int targetUid = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg, intent);
4663 if (targetUid < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004664 return;
4665 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07004666
4667 grantUriPermissionUncheckedFromIntentLocked(targetUid, targetPkg, intent, owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004668 }
4669
4670 public void grantUriPermission(IApplicationThread caller, String targetPkg,
4671 Uri uri, int modeFlags) {
4672 synchronized(this) {
4673 final ProcessRecord r = getRecordForAppLocked(caller);
4674 if (r == null) {
4675 throw new SecurityException("Unable to find app for caller "
4676 + caller
4677 + " when granting permission to uri " + uri);
4678 }
4679 if (targetPkg == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004680 throw new IllegalArgumentException("null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004681 }
4682 if (uri == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004683 throw new IllegalArgumentException("null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004684 }
4685
4686 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
4687 null);
4688 }
4689 }
4690
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004691 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004692 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
4693 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
4694 HashMap<Uri, UriPermission> perms
4695 = mGrantedUriPermissions.get(perm.uid);
4696 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004697 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004698 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004699 perms.remove(perm.uri);
4700 if (perms.size() == 0) {
4701 mGrantedUriPermissions.remove(perm.uid);
4702 }
4703 }
4704 }
4705 }
4706
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004707 private void revokeUriPermissionLocked(int callingUid, Uri uri,
4708 int modeFlags) {
4709 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4710 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4711 if (modeFlags == 0) {
4712 return;
4713 }
4714
Joe Onorato8a9b2202010-02-26 18:56:32 -08004715 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004716 "Revoking all granted permissions to " + uri);
4717
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004718 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004719
4720 final String authority = uri.getAuthority();
4721 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004722 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004723 if (cpr != null) {
4724 pi = cpr.info;
4725 } else {
4726 try {
4727 pi = pm.resolveContentProvider(authority,
4728 PackageManager.GET_URI_PERMISSION_PATTERNS);
4729 } catch (RemoteException ex) {
4730 }
4731 }
4732 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004733 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004734 return;
4735 }
4736
4737 // Does the caller have this permission on the URI?
Dianne Hackborn48058e82010-09-27 16:53:23 -07004738 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004739 // Right now, if you are not the original owner of the permission,
4740 // you are not allowed to revoke it.
4741 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4742 throw new SecurityException("Uid " + callingUid
4743 + " does not have permission to uri " + uri);
4744 //}
4745 }
4746
4747 // Go through all of the permissions and remove any that match.
4748 final List<String> SEGMENTS = uri.getPathSegments();
4749 if (SEGMENTS != null) {
4750 final int NS = SEGMENTS.size();
4751 int N = mGrantedUriPermissions.size();
4752 for (int i=0; i<N; i++) {
4753 HashMap<Uri, UriPermission> perms
4754 = mGrantedUriPermissions.valueAt(i);
4755 Iterator<UriPermission> it = perms.values().iterator();
4756 toploop:
4757 while (it.hasNext()) {
4758 UriPermission perm = it.next();
4759 Uri targetUri = perm.uri;
4760 if (!authority.equals(targetUri.getAuthority())) {
4761 continue;
4762 }
4763 List<String> targetSegments = targetUri.getPathSegments();
4764 if (targetSegments == null) {
4765 continue;
4766 }
4767 if (targetSegments.size() < NS) {
4768 continue;
4769 }
4770 for (int j=0; j<NS; j++) {
4771 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
4772 continue toploop;
4773 }
4774 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004775 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004776 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004777 perm.clearModes(modeFlags);
4778 if (perm.modeFlags == 0) {
4779 it.remove();
4780 }
4781 }
4782 if (perms.size() == 0) {
4783 mGrantedUriPermissions.remove(
4784 mGrantedUriPermissions.keyAt(i));
4785 N--;
4786 i--;
4787 }
4788 }
4789 }
4790 }
4791
4792 public void revokeUriPermission(IApplicationThread caller, Uri uri,
4793 int modeFlags) {
4794 synchronized(this) {
4795 final ProcessRecord r = getRecordForAppLocked(caller);
4796 if (r == null) {
4797 throw new SecurityException("Unable to find app for caller "
4798 + caller
4799 + " when revoking permission to uri " + uri);
4800 }
4801 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004802 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004803 return;
4804 }
4805
4806 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4807 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4808 if (modeFlags == 0) {
4809 return;
4810 }
4811
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004812 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004813
4814 final String authority = uri.getAuthority();
4815 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004816 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004817 if (cpr != null) {
4818 pi = cpr.info;
4819 } else {
4820 try {
4821 pi = pm.resolveContentProvider(authority,
4822 PackageManager.GET_URI_PERMISSION_PATTERNS);
4823 } catch (RemoteException ex) {
4824 }
4825 }
4826 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004827 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004828 return;
4829 }
4830
4831 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
4832 }
4833 }
4834
Dianne Hackborn7e269642010-08-25 19:50:20 -07004835 @Override
4836 public IBinder newUriPermissionOwner(String name) {
4837 synchronized(this) {
4838 UriPermissionOwner owner = new UriPermissionOwner(this, name);
4839 return owner.getExternalTokenLocked();
4840 }
4841 }
4842
4843 @Override
4844 public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg,
4845 Uri uri, int modeFlags) {
4846 synchronized(this) {
4847 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4848 if (owner == null) {
4849 throw new IllegalArgumentException("Unknown owner: " + token);
4850 }
4851 if (fromUid != Binder.getCallingUid()) {
4852 if (Binder.getCallingUid() != Process.myUid()) {
4853 // Only system code can grant URI permissions on behalf
4854 // of other users.
4855 throw new SecurityException("nice try");
4856 }
4857 }
4858 if (targetPkg == null) {
4859 throw new IllegalArgumentException("null target");
4860 }
4861 if (uri == null) {
4862 throw new IllegalArgumentException("null uri");
4863 }
4864
4865 grantUriPermissionLocked(fromUid, targetPkg, uri, modeFlags, owner);
4866 }
4867 }
4868
4869 @Override
4870 public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode) {
4871 synchronized(this) {
4872 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4873 if (owner == null) {
4874 throw new IllegalArgumentException("Unknown owner: " + token);
4875 }
4876
4877 if (uri == null) {
4878 owner.removeUriPermissionsLocked(mode);
4879 } else {
4880 owner.removeUriPermissionLocked(uri, mode);
4881 }
4882 }
4883 }
4884
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004885 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
4886 synchronized (this) {
4887 ProcessRecord app =
4888 who != null ? getRecordForAppLocked(who) : null;
4889 if (app == null) return;
4890
4891 Message msg = Message.obtain();
4892 msg.what = WAIT_FOR_DEBUGGER_MSG;
4893 msg.obj = app;
4894 msg.arg1 = waiting ? 1 : 0;
4895 mHandler.sendMessage(msg);
4896 }
4897 }
4898
4899 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
4900 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08004901 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004902 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08004903 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004904 }
4905
4906 // =========================================================
4907 // TASK MANAGEMENT
4908 // =========================================================
4909
4910 public List getTasks(int maxNum, int flags,
4911 IThumbnailReceiver receiver) {
4912 ArrayList list = new ArrayList();
4913
4914 PendingThumbnailsRecord pending = null;
4915 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004916 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004917
4918 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004919 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004920 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
4921 + ", receiver=" + receiver);
4922
4923 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
4924 != PackageManager.PERMISSION_GRANTED) {
4925 if (receiver != null) {
4926 // If the caller wants to wait for pending thumbnails,
4927 // it ain't gonna get them.
4928 try {
4929 receiver.finished();
4930 } catch (RemoteException ex) {
4931 }
4932 }
4933 String msg = "Permission Denial: getTasks() from pid="
4934 + Binder.getCallingPid()
4935 + ", uid=" + Binder.getCallingUid()
4936 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004937 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004938 throw new SecurityException(msg);
4939 }
4940
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004941 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004942 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004943 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004944 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004945 TaskRecord curTask = null;
4946 int numActivities = 0;
4947 int numRunning = 0;
4948 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004949 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004950 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004951 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004952
4953 // Initialize state for next task if needed.
4954 if (top == null ||
4955 (top.state == ActivityState.INITIALIZING
4956 && top.task == r.task)) {
4957 top = r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004958 curTask = r.task;
4959 numActivities = numRunning = 0;
4960 }
4961
4962 // Add 'r' into the current task.
4963 numActivities++;
4964 if (r.app != null && r.app.thread != null) {
4965 numRunning++;
4966 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004967
Joe Onorato8a9b2202010-02-26 18:56:32 -08004968 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004969 TAG, r.intent.getComponent().flattenToShortString()
4970 + ": task=" + r.task);
4971
4972 // If the next one is a different task, generate a new
4973 // TaskInfo entry for what we have.
4974 if (next == null || next.task != curTask) {
4975 ActivityManager.RunningTaskInfo ci
4976 = new ActivityManager.RunningTaskInfo();
4977 ci.id = curTask.taskId;
4978 ci.baseActivity = r.intent.getComponent();
4979 ci.topActivity = top.intent.getComponent();
Dianne Hackbornf26fd992011-04-08 18:14:09 -07004980 if (top.thumbHolder != null) {
4981 ci.description = top.thumbHolder.lastDescription;
4982 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004983 ci.numActivities = numActivities;
4984 ci.numRunning = numRunning;
4985 //System.out.println(
4986 // "#" + maxNum + ": " + " descr=" + ci.description);
4987 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004988 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004989 TAG, "State=" + top.state + "Idle=" + top.idle
4990 + " app=" + top.app
4991 + " thr=" + (top.app != null ? top.app.thread : null));
4992 if (top.state == ActivityState.RESUMED
4993 || top.state == ActivityState.PAUSING) {
4994 if (top.idle && top.app != null
4995 && top.app.thread != null) {
4996 topRecord = top;
4997 topThumbnail = top.app.thread;
4998 } else {
4999 top.thumbnailNeeded = true;
5000 }
5001 }
5002 if (pending == null) {
5003 pending = new PendingThumbnailsRecord(receiver);
5004 }
5005 pending.pendingRecords.add(top);
5006 }
5007 list.add(ci);
5008 maxNum--;
5009 top = null;
5010 }
5011 }
5012
5013 if (pending != null) {
5014 mPendingThumbnails.add(pending);
5015 }
5016 }
5017
Joe Onorato8a9b2202010-02-26 18:56:32 -08005018 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005019
5020 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005021 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005022 try {
5023 topThumbnail.requestThumbnail(topRecord);
5024 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005025 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005026 sendPendingThumbnail(null, topRecord, null, null, true);
5027 }
5028 }
5029
5030 if (pending == null && receiver != null) {
5031 // In this case all thumbnails were available and the client
5032 // is being asked to be told when the remaining ones come in...
5033 // which is unusually, since the top-most currently running
5034 // activity should never have a canned thumbnail! Oh well.
5035 try {
5036 receiver.finished();
5037 } catch (RemoteException ex) {
5038 }
5039 }
5040
5041 return list;
5042 }
5043
5044 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
5045 int flags) {
5046 synchronized (this) {
5047 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
5048 "getRecentTasks()");
5049
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005050 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07005051
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005052 final int N = mRecentTasks.size();
5053 ArrayList<ActivityManager.RecentTaskInfo> res
5054 = new ArrayList<ActivityManager.RecentTaskInfo>(
5055 maxNum < N ? maxNum : N);
5056 for (int i=0; i<N && maxNum > 0; i++) {
5057 TaskRecord tr = mRecentTasks.get(i);
5058 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
5059 || (tr.intent == null)
5060 || ((tr.intent.getFlags()
5061 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
5062 ActivityManager.RecentTaskInfo rti
5063 = new ActivityManager.RecentTaskInfo();
5064 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
Dianne Hackbornd94df452011-02-16 18:53:31 -08005065 rti.persistentId = tr.taskId;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005066 rti.baseIntent = new Intent(
5067 tr.intent != null ? tr.intent : tr.affinityIntent);
5068 rti.origActivity = tr.origActivity;
Dianne Hackbornd2835932010-12-13 16:28:46 -08005069 rti.description = tr.lastDescription;
5070
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07005071 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
5072 // Check whether this activity is currently available.
5073 try {
5074 if (rti.origActivity != null) {
5075 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
5076 continue;
5077 }
5078 } else if (rti.baseIntent != null) {
5079 if (pm.queryIntentActivities(rti.baseIntent,
5080 null, 0) == null) {
5081 continue;
5082 }
5083 }
5084 } catch (RemoteException e) {
5085 // Will never happen.
5086 }
5087 }
5088
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005089 res.add(rti);
5090 maxNum--;
5091 }
5092 }
5093 return res;
5094 }
5095 }
5096
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005097 private TaskRecord taskForIdLocked(int id) {
5098 final int N = mRecentTasks.size();
5099 for (int i=0; i<N; i++) {
5100 TaskRecord tr = mRecentTasks.get(i);
5101 if (tr.taskId == id) {
5102 return tr;
Dianne Hackbornd94df452011-02-16 18:53:31 -08005103 }
5104 }
5105 return null;
5106 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005107
5108 public ActivityManager.TaskThumbnails getTaskThumbnails(int id) {
5109 synchronized (this) {
5110 enforceCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER,
5111 "getTaskThumbnails()");
5112 TaskRecord tr = taskForIdLocked(id);
5113 if (tr != null) {
5114 return mMainStack.getTaskThumbnailsLocked(tr);
5115 }
5116 }
5117 return null;
5118 }
5119
5120 public boolean removeSubTask(int taskId, int subTaskIndex) {
5121 synchronized (this) {
5122 enforceCallingPermission(android.Manifest.permission.REMOVE_TASKS,
5123 "removeSubTask()");
5124 long ident = Binder.clearCallingIdentity();
5125 try {
5126 return mMainStack.removeTaskActivitiesLocked(taskId, subTaskIndex) != null;
5127 } finally {
5128 Binder.restoreCallingIdentity(ident);
5129 }
5130 }
5131 }
5132
Dianne Hackborn8894cc52011-07-01 16:28:17 -07005133 private void cleanUpRemovedTaskLocked(ActivityRecord root, boolean killProcesses) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005134 TaskRecord tr = root.task;
5135 Intent baseIntent = new Intent(
5136 tr.intent != null ? tr.intent : tr.affinityIntent);
5137 ComponentName component = baseIntent.getComponent();
5138 if (component == null) {
5139 Slog.w(TAG, "Now component for base intent of task: " + tr);
5140 return;
5141 }
5142
5143 // Find any running services associated with this app.
5144 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
5145 for (ServiceRecord sr : mServices.values()) {
5146 if (sr.packageName.equals(component.getPackageName())) {
5147 services.add(sr);
5148 }
5149 }
5150
5151 // Take care of any running services associated with the app.
5152 for (int i=0; i<services.size(); i++) {
5153 ServiceRecord sr = services.get(i);
5154 if (sr.startRequested) {
5155 if ((sr.serviceInfo.flags&ServiceInfo.FLAG_STOP_WITH_TASK) != 0) {
Dianne Hackborn8894cc52011-07-01 16:28:17 -07005156 Slog.i(TAG, "Stopping service " + sr.shortName + ": remove task");
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005157 stopServiceLocked(sr);
5158 } else {
5159 sr.pendingStarts.add(new ServiceRecord.StartItem(sr, true,
5160 sr.makeNextStartId(), baseIntent, -1));
5161 if (sr.app != null && sr.app.thread != null) {
5162 sendServiceArgsLocked(sr, false);
5163 }
5164 }
5165 }
5166 }
5167
Dianne Hackborn8894cc52011-07-01 16:28:17 -07005168 if (killProcesses) {
5169 // Find any running processes associated with this app.
5170 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
5171 SparseArray<ProcessRecord> appProcs
5172 = mProcessNames.getMap().get(component.getPackageName());
5173 if (appProcs != null) {
5174 for (int i=0; i<appProcs.size(); i++) {
5175 procs.add(appProcs.valueAt(i));
5176 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005177 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005178
Dianne Hackborn8894cc52011-07-01 16:28:17 -07005179 // Kill the running processes.
5180 for (int i=0; i<procs.size(); i++) {
5181 ProcessRecord pr = procs.get(i);
5182 if (pr.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {
5183 Slog.i(TAG, "Killing " + pr.toShortString() + ": remove task");
5184 EventLog.writeEvent(EventLogTags.AM_KILL, pr.pid,
5185 pr.processName, pr.setAdj, "remove task");
5186 Process.killProcessQuiet(pr.pid);
5187 } else {
5188 pr.waitingToKill = "remove task";
5189 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005190 }
5191 }
5192 }
5193
5194 public boolean removeTask(int taskId, int flags) {
5195 synchronized (this) {
5196 enforceCallingPermission(android.Manifest.permission.REMOVE_TASKS,
5197 "removeTask()");
5198 long ident = Binder.clearCallingIdentity();
5199 try {
5200 ActivityRecord r = mMainStack.removeTaskActivitiesLocked(taskId, -1);
5201 if (r != null) {
5202 mRecentTasks.remove(r.task);
Dianne Hackborn8894cc52011-07-01 16:28:17 -07005203 cleanUpRemovedTaskLocked(r,
5204 (flags&ActivityManager.REMOVE_TASK_KILL_PROCESS) != 0);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005205 return true;
5206 }
5207 } finally {
5208 Binder.restoreCallingIdentity(ident);
5209 }
5210 }
5211 return false;
5212 }
Dianne Hackbornd94df452011-02-16 18:53:31 -08005213
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005214 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
5215 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005216 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005217 TaskRecord jt = startTask;
5218
5219 // First look backwards
5220 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005221 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005222 if (r.task != jt) {
5223 jt = r.task;
5224 if (affinity.equals(jt.affinity)) {
5225 return j;
5226 }
5227 }
5228 }
5229
5230 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005231 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005232 jt = startTask;
5233 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005234 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005235 if (r.task != jt) {
5236 if (affinity.equals(jt.affinity)) {
5237 return j;
5238 }
5239 jt = r.task;
5240 }
5241 }
5242
5243 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005244 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005245 return N-1;
5246 }
5247
5248 return -1;
5249 }
5250
5251 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005252 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005253 */
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005254 public void moveTaskToFront(int task, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005255 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5256 "moveTaskToFront()");
5257
5258 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005259 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5260 Binder.getCallingUid(), "Task to front")) {
5261 return;
5262 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005263 final long origId = Binder.clearCallingIdentity();
5264 try {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005265 TaskRecord tr = taskForIdLocked(task);
5266 if (tr != null) {
5267 if ((flags&ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
5268 mMainStack.mUserLeaving = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005269 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005270 if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
5271 // Caller wants the home activity moved with it. To accomplish this,
5272 // we'll just move the home task to the top first.
5273 mMainStack.moveHomeToFrontLocked();
5274 }
5275 mMainStack.moveTaskToFrontLocked(tr, null);
5276 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005277 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005278 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
5279 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005280 if (hr.task.taskId == task) {
Dianne Hackbornd94df452011-02-16 18:53:31 -08005281 if ((flags&ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
5282 mMainStack.mUserLeaving = true;
5283 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005284 if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
5285 // Caller wants the home activity moved with it. To accomplish this,
5286 // we'll just move the home task to the top first.
5287 mMainStack.moveHomeToFrontLocked();
5288 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005289 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005290 return;
5291 }
5292 }
5293 } finally {
5294 Binder.restoreCallingIdentity(origId);
5295 }
5296 }
5297 }
5298
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005299 public void moveTaskToBack(int task) {
5300 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5301 "moveTaskToBack()");
5302
5303 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005304 if (mMainStack.mResumedActivity != null
5305 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005306 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5307 Binder.getCallingUid(), "Task to back")) {
5308 return;
5309 }
5310 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005311 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005312 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005313 Binder.restoreCallingIdentity(origId);
5314 }
5315 }
5316
5317 /**
5318 * Moves an activity, and all of the other activities within the same task, to the bottom
5319 * of the history stack. The activity's order within the task is unchanged.
5320 *
5321 * @param token A reference to the activity we wish to move
5322 * @param nonRoot If false then this only works if the activity is the root
5323 * of a task; if true it will work for any activity in a task.
5324 * @return Returns true if the move completed, false if not.
5325 */
5326 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
5327 synchronized(this) {
5328 final long origId = Binder.clearCallingIdentity();
5329 int taskId = getTaskForActivityLocked(token, !nonRoot);
5330 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005331 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005332 }
5333 Binder.restoreCallingIdentity(origId);
5334 }
5335 return false;
5336 }
5337
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005338 public void moveTaskBackwards(int task) {
5339 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5340 "moveTaskBackwards()");
5341
5342 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005343 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5344 Binder.getCallingUid(), "Task backwards")) {
5345 return;
5346 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005347 final long origId = Binder.clearCallingIdentity();
5348 moveTaskBackwardsLocked(task);
5349 Binder.restoreCallingIdentity(origId);
5350 }
5351 }
5352
5353 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005354 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005355 }
5356
5357 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
5358 synchronized(this) {
5359 return getTaskForActivityLocked(token, onlyRoot);
5360 }
5361 }
5362
5363 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005364 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005365 TaskRecord lastTask = null;
5366 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005367 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005368 if (r == token) {
5369 if (!onlyRoot || lastTask != r.task) {
5370 return r.task.taskId;
5371 }
5372 return -1;
5373 }
5374 lastTask = r.task;
5375 }
5376
5377 return -1;
5378 }
5379
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005380 public void finishOtherInstances(IBinder token, ComponentName className) {
5381 synchronized(this) {
5382 final long origId = Binder.clearCallingIdentity();
5383
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005384 int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005385 TaskRecord lastTask = null;
5386 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005387 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005388 if (r.realActivity.equals(className)
5389 && r != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005390 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005391 null, "others")) {
5392 i--;
5393 N--;
5394 }
5395 }
5396 lastTask = r.task;
5397 }
5398
5399 Binder.restoreCallingIdentity(origId);
5400 }
5401 }
5402
5403 // =========================================================
5404 // THUMBNAILS
5405 // =========================================================
5406
5407 public void reportThumbnail(IBinder token,
5408 Bitmap thumbnail, CharSequence description) {
5409 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
5410 final long origId = Binder.clearCallingIdentity();
5411 sendPendingThumbnail(null, token, thumbnail, description, true);
5412 Binder.restoreCallingIdentity(origId);
5413 }
5414
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005415 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005416 Bitmap thumbnail, CharSequence description, boolean always) {
5417 TaskRecord task = null;
5418 ArrayList receivers = null;
5419
5420 //System.out.println("Send pending thumbnail: " + r);
5421
5422 synchronized(this) {
5423 if (r == null) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07005424 r = mMainStack.isInStackLocked(token);
5425 if (r == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005426 return;
5427 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005428 }
Dianne Hackbornf26fd992011-04-08 18:14:09 -07005429 if (thumbnail == null && r.thumbHolder != null) {
5430 thumbnail = r.thumbHolder.lastThumbnail;
5431 description = r.thumbHolder.lastDescription;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005432 }
5433 if (thumbnail == null && !always) {
5434 // If there is no thumbnail, and this entry is not actually
5435 // going away, then abort for now and pick up the next
5436 // thumbnail we get.
5437 return;
5438 }
5439 task = r.task;
5440
5441 int N = mPendingThumbnails.size();
5442 int i=0;
5443 while (i<N) {
5444 PendingThumbnailsRecord pr =
5445 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
5446 //System.out.println("Looking in " + pr.pendingRecords);
5447 if (pr.pendingRecords.remove(r)) {
5448 if (receivers == null) {
5449 receivers = new ArrayList();
5450 }
5451 receivers.add(pr);
5452 if (pr.pendingRecords.size() == 0) {
5453 pr.finished = true;
5454 mPendingThumbnails.remove(i);
5455 N--;
5456 continue;
5457 }
5458 }
5459 i++;
5460 }
5461 }
5462
5463 if (receivers != null) {
5464 final int N = receivers.size();
5465 for (int i=0; i<N; i++) {
5466 try {
5467 PendingThumbnailsRecord pr =
5468 (PendingThumbnailsRecord)receivers.get(i);
5469 pr.receiver.newThumbnail(
5470 task != null ? task.taskId : -1, thumbnail, description);
5471 if (pr.finished) {
5472 pr.receiver.finished();
5473 }
5474 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005475 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005476 }
5477 }
5478 }
5479 }
5480
5481 // =========================================================
5482 // CONTENT PROVIDERS
5483 // =========================================================
5484
Jeff Brown10e89712011-07-08 18:52:57 -07005485 private final List<ProviderInfo> generateApplicationProvidersLocked(ProcessRecord app) {
5486 List<ProviderInfo> providers = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005487 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005488 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005489 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005490 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005491 } catch (RemoteException ex) {
5492 }
5493 if (providers != null) {
5494 final int N = providers.size();
5495 for (int i=0; i<N; i++) {
5496 ProviderInfo cpi =
5497 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005498 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005499 if (cpr == null) {
5500 cpr = new ContentProviderRecord(cpi, app.info);
5501 mProvidersByClass.put(cpi.name, cpr);
5502 }
5503 app.pubProviders.put(cpi.name, cpr);
5504 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005505 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005506 }
5507 }
5508 return providers;
5509 }
5510
5511 private final String checkContentProviderPermissionLocked(
Dianne Hackbornb424b632010-08-18 15:59:05 -07005512 ProviderInfo cpi, ProcessRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005513 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
5514 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
5515 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005516 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005517 == PackageManager.PERMISSION_GRANTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005518 return null;
5519 }
5520 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005521 cpi.applicationInfo.uid, cpi.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005522 == PackageManager.PERMISSION_GRANTED) {
5523 return null;
5524 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005525
5526 PathPermission[] pps = cpi.pathPermissions;
5527 if (pps != null) {
5528 int i = pps.length;
5529 while (i > 0) {
5530 i--;
5531 PathPermission pp = pps[i];
5532 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005533 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005534 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005535 return null;
5536 }
5537 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005538 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005539 == PackageManager.PERMISSION_GRANTED) {
5540 return null;
5541 }
5542 }
5543 }
5544
Dianne Hackbornb424b632010-08-18 15:59:05 -07005545 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
5546 if (perms != null) {
5547 for (Map.Entry<Uri, UriPermission> uri : perms.entrySet()) {
5548 if (uri.getKey().getAuthority().equals(cpi.authority)) {
5549 return null;
5550 }
5551 }
5552 }
5553
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005554 String msg;
5555 if (!cpi.exported) {
5556 msg = "Permission Denial: opening provider " + cpi.name
5557 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5558 + ", uid=" + callingUid + ") that is not exported from uid "
5559 + cpi.applicationInfo.uid;
5560 } else {
5561 msg = "Permission Denial: opening provider " + cpi.name
5562 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5563 + ", uid=" + callingUid + ") requires "
5564 + cpi.readPermission + " or " + cpi.writePermission;
5565 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005566 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005567 return msg;
5568 }
5569
5570 private final ContentProviderHolder getContentProviderImpl(
5571 IApplicationThread caller, String name) {
5572 ContentProviderRecord cpr;
5573 ProviderInfo cpi = null;
5574
5575 synchronized(this) {
5576 ProcessRecord r = null;
5577 if (caller != null) {
5578 r = getRecordForAppLocked(caller);
5579 if (r == null) {
5580 throw new SecurityException(
5581 "Unable to find app for caller " + caller
5582 + " (pid=" + Binder.getCallingPid()
5583 + ") when getting content provider " + name);
5584 }
5585 }
5586
5587 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07005588 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005589 if (cpr != null) {
5590 cpi = cpr.info;
Dianne Hackbornb424b632010-08-18 15:59:05 -07005591 String msg;
5592 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5593 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005594 }
5595
5596 if (r != null && cpr.canRunHere(r)) {
5597 // This provider has been published or is in the process
5598 // of being published... but it is also allowed to run
5599 // in the caller's process, so don't make a connection
5600 // and just let the caller instantiate its own instance.
5601 if (cpr.provider != null) {
5602 // don't give caller the provider object, it needs
5603 // to make its own.
5604 cpr = new ContentProviderRecord(cpr);
5605 }
5606 return cpr;
5607 }
5608
5609 final long origId = Binder.clearCallingIdentity();
5610
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005611 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005612 // return it right away.
5613 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005614 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005615 "Adding provider requested by "
5616 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005617 + cpr.info.processName);
5618 Integer cnt = r.conProviders.get(cpr);
5619 if (cnt == null) {
5620 r.conProviders.put(cpr, new Integer(1));
5621 } else {
5622 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5623 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005624 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07005625 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
5626 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07005627 // make sure to count it as being accessed and thus
5628 // back up on the LRU list. This is good because
5629 // content providers are often expensive to start.
5630 updateLruProcessLocked(cpr.app, false, true);
5631 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07005632 } else {
5633 cpr.externals++;
5634 }
5635
5636 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005637 updateOomAdjLocked(cpr.app);
5638 }
5639
5640 Binder.restoreCallingIdentity(origId);
5641
5642 } else {
5643 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005644 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005645 resolveContentProvider(name,
5646 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005647 } catch (RemoteException ex) {
5648 }
5649 if (cpi == null) {
5650 return null;
5651 }
5652
Dianne Hackbornb424b632010-08-18 15:59:05 -07005653 String msg;
5654 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5655 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005656 }
5657
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07005658 if (!mProcessesReady && !mDidUpdate && !mWaitingUpdate
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005659 && !cpi.processName.equals("system")) {
5660 // If this content provider does not run in the system
5661 // process, and the system is not yet ready to run other
5662 // processes, then fail fast instead of hanging.
5663 throw new IllegalArgumentException(
5664 "Attempt to launch content provider before system ready");
5665 }
5666
Dianne Hackborn860755f2010-06-03 18:47:52 -07005667 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005668 final boolean firstClass = cpr == null;
5669 if (firstClass) {
5670 try {
5671 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005672 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005673 getApplicationInfo(
5674 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005675 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005676 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005677 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005678 + cpi.name);
5679 return null;
5680 }
5681 cpr = new ContentProviderRecord(cpi, ai);
5682 } catch (RemoteException ex) {
5683 // pm is in same process, this will never happen.
5684 }
5685 }
5686
5687 if (r != null && cpr.canRunHere(r)) {
5688 // If this is a multiprocess provider, then just return its
5689 // info and allow the caller to instantiate it. Only do
5690 // this if the provider is the same user as the caller's
5691 // process, or can run as root (so can be in any process).
5692 return cpr;
5693 }
5694
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005695 if (DEBUG_PROVIDER) {
5696 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08005697 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005698 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005699 }
5700
5701 // This is single process, and our app is now connecting to it.
5702 // See if we are already in the process of launching this
5703 // provider.
5704 final int N = mLaunchingProviders.size();
5705 int i;
5706 for (i=0; i<N; i++) {
5707 if (mLaunchingProviders.get(i) == cpr) {
5708 break;
5709 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005710 }
5711
5712 // If the provider is not already being launched, then get it
5713 // started.
5714 if (i >= N) {
5715 final long origId = Binder.clearCallingIdentity();
Dianne Hackborne7f97212011-02-24 14:40:20 -08005716
5717 try {
5718 // Content provider is now in use, its package can't be stopped.
5719 try {
5720 AppGlobals.getPackageManager().setPackageStoppedState(
5721 cpr.appInfo.packageName, false);
5722 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08005723 } catch (IllegalArgumentException e) {
5724 Slog.w(TAG, "Failed trying to unstop package "
5725 + cpr.appInfo.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08005726 }
5727
5728 ProcessRecord proc = startProcessLocked(cpi.processName,
5729 cpr.appInfo, false, 0, "content provider",
5730 new ComponentName(cpi.applicationInfo.packageName,
5731 cpi.name), false);
5732 if (proc == null) {
5733 Slog.w(TAG, "Unable to launch app "
5734 + cpi.applicationInfo.packageName + "/"
5735 + cpi.applicationInfo.uid + " for provider "
5736 + name + ": process is bad");
5737 return null;
5738 }
5739 cpr.launchingApp = proc;
5740 mLaunchingProviders.add(cpr);
5741 } finally {
5742 Binder.restoreCallingIdentity(origId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005743 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005744 }
5745
5746 // Make sure the provider is published (the same provider class
5747 // may be published under multiple names).
5748 if (firstClass) {
5749 mProvidersByClass.put(cpi.name, cpr);
5750 }
5751 mProvidersByName.put(name, cpr);
5752
5753 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005754 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005755 "Adding provider requested by "
5756 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005757 + cpr.info.processName);
5758 Integer cnt = r.conProviders.get(cpr);
5759 if (cnt == null) {
5760 r.conProviders.put(cpr, new Integer(1));
5761 } else {
5762 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5763 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005764 cpr.clients.add(r);
5765 } else {
5766 cpr.externals++;
5767 }
5768 }
5769 }
5770
5771 // Wait for the provider to be published...
5772 synchronized (cpr) {
5773 while (cpr.provider == null) {
5774 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005775 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005776 + cpi.applicationInfo.packageName + "/"
5777 + cpi.applicationInfo.uid + " for provider "
5778 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005779 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005780 cpi.applicationInfo.packageName,
5781 cpi.applicationInfo.uid, name);
5782 return null;
5783 }
5784 try {
5785 cpr.wait();
5786 } catch (InterruptedException ex) {
5787 }
5788 }
5789 }
5790 return cpr;
5791 }
5792
5793 public final ContentProviderHolder getContentProvider(
5794 IApplicationThread caller, String name) {
5795 if (caller == null) {
5796 String msg = "null IApplicationThread when getting content provider "
5797 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005798 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005799 throw new SecurityException(msg);
5800 }
5801
5802 return getContentProviderImpl(caller, name);
5803 }
5804
5805 private ContentProviderHolder getContentProviderExternal(String name) {
5806 return getContentProviderImpl(null, name);
5807 }
5808
5809 /**
5810 * Drop a content provider from a ProcessRecord's bookkeeping
5811 * @param cpr
5812 */
5813 public void removeContentProvider(IApplicationThread caller, String name) {
5814 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005815 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005816 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005817 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005818 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005819 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005820 return;
5821 }
5822 final ProcessRecord r = getRecordForAppLocked(caller);
5823 if (r == null) {
5824 throw new SecurityException(
5825 "Unable to find app for caller " + caller +
5826 " when removing content provider " + name);
5827 }
5828 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005829 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005830 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005831 + r.info.processName + " from process "
5832 + localCpr.appInfo.processName);
5833 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005834 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08005835 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005836 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005837 return;
5838 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005839 Integer cnt = r.conProviders.get(localCpr);
5840 if (cnt == null || cnt.intValue() <= 1) {
5841 localCpr.clients.remove(r);
5842 r.conProviders.remove(localCpr);
5843 } else {
5844 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
5845 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005846 }
5847 updateOomAdjLocked();
5848 }
5849 }
5850
5851 private void removeContentProviderExternal(String name) {
5852 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005853 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005854 if(cpr == null) {
5855 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005856 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005857 return;
5858 }
5859
5860 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005861 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005862 localCpr.externals--;
5863 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005864 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005865 }
5866 updateOomAdjLocked();
5867 }
5868 }
5869
5870 public final void publishContentProviders(IApplicationThread caller,
5871 List<ContentProviderHolder> providers) {
5872 if (providers == null) {
5873 return;
5874 }
5875
5876 synchronized(this) {
5877 final ProcessRecord r = getRecordForAppLocked(caller);
5878 if (r == null) {
5879 throw new SecurityException(
5880 "Unable to find app for caller " + caller
5881 + " (pid=" + Binder.getCallingPid()
5882 + ") when publishing content providers");
5883 }
5884
5885 final long origId = Binder.clearCallingIdentity();
5886
5887 final int N = providers.size();
5888 for (int i=0; i<N; i++) {
5889 ContentProviderHolder src = providers.get(i);
5890 if (src == null || src.info == null || src.provider == null) {
5891 continue;
5892 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005893 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005894 if (dst != null) {
5895 mProvidersByClass.put(dst.info.name, dst);
5896 String names[] = dst.info.authority.split(";");
5897 for (int j = 0; j < names.length; j++) {
5898 mProvidersByName.put(names[j], dst);
5899 }
5900
5901 int NL = mLaunchingProviders.size();
5902 int j;
5903 for (j=0; j<NL; j++) {
5904 if (mLaunchingProviders.get(j) == dst) {
5905 mLaunchingProviders.remove(j);
5906 j--;
5907 NL--;
5908 }
5909 }
5910 synchronized (dst) {
5911 dst.provider = src.provider;
5912 dst.app = r;
5913 dst.notifyAll();
5914 }
5915 updateOomAdjLocked(r);
5916 }
5917 }
5918
5919 Binder.restoreCallingIdentity(origId);
5920 }
5921 }
5922
5923 public static final void installSystemProviders() {
Jeff Brown10e89712011-07-08 18:52:57 -07005924 List<ProviderInfo> providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06005925 synchronized (mSelf) {
5926 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
5927 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005928 if (providers != null) {
5929 for (int i=providers.size()-1; i>=0; i--) {
5930 ProviderInfo pi = (ProviderInfo)providers.get(i);
5931 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5932 Slog.w(TAG, "Not installing system proc provider " + pi.name
5933 + ": not system .apk");
5934 providers.remove(i);
5935 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005936 }
5937 }
5938 }
Josh Bartel2ecce342010-02-25 10:55:48 -06005939 if (providers != null) {
5940 mSystemThread.installSystemProviders(providers);
5941 }
Svetoslav Ganov54d068e2011-03-02 12:58:40 -08005942
5943 mSelf.mCoreSettingsObserver = new CoreSettingsObserver(mSelf);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005944 }
5945
Dianne Hackborncca1f0e2010-09-26 18:34:53 -07005946 /**
5947 * Allows app to retrieve the MIME type of a URI without having permission
5948 * to access its content provider.
5949 *
5950 * CTS tests for this functionality can be run with "runtest cts-appsecurity".
5951 *
5952 * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
5953 * src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
5954 */
5955 public String getProviderMimeType(Uri uri) {
5956 final String name = uri.getAuthority();
5957 final long ident = Binder.clearCallingIdentity();
5958 ContentProviderHolder holder = null;
5959
5960 try {
5961 holder = getContentProviderExternal(name);
5962 if (holder != null) {
5963 return holder.provider.getType(uri);
5964 }
5965 } catch (RemoteException e) {
5966 Log.w(TAG, "Content provider dead retrieving " + uri, e);
5967 return null;
5968 } finally {
5969 if (holder != null) {
5970 removeContentProviderExternal(name);
5971 }
5972 Binder.restoreCallingIdentity(ident);
5973 }
5974
5975 return null;
5976 }
5977
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005978 // =========================================================
5979 // GLOBAL MANAGEMENT
5980 // =========================================================
5981
5982 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
5983 ApplicationInfo info, String customProcess) {
5984 String proc = customProcess != null ? customProcess : info.processName;
5985 BatteryStatsImpl.Uid.Proc ps = null;
5986 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5987 synchronized (stats) {
5988 ps = stats.getProcessStatsLocked(info.uid, proc);
5989 }
5990 return new ProcessRecord(ps, thread, info, proc);
5991 }
5992
5993 final ProcessRecord addAppLocked(ApplicationInfo info) {
5994 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
5995
5996 if (app == null) {
5997 app = newProcessRecordLocked(null, info, null);
5998 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08005999 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006000 }
6001
Dianne Hackborne7f97212011-02-24 14:40:20 -08006002 // This package really, really can not be stopped.
6003 try {
6004 AppGlobals.getPackageManager().setPackageStoppedState(
6005 info.packageName, false);
6006 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08006007 } catch (IllegalArgumentException e) {
6008 Slog.w(TAG, "Failed trying to unstop package "
6009 + info.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08006010 }
6011
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006012 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
6013 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
6014 app.persistent = true;
6015 app.maxAdj = CORE_SERVER_ADJ;
6016 }
6017 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
6018 mPersistentStartingProcesses.add(app);
6019 startProcessLocked(app, "added application", app.processName);
6020 }
6021
6022 return app;
6023 }
6024
6025 public void unhandledBack() {
6026 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
6027 "unhandledBack()");
6028
6029 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006030 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08006031 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006032 TAG, "Performing unhandledBack(): stack size = " + count);
6033 if (count > 1) {
6034 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006035 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006036 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
6037 Binder.restoreCallingIdentity(origId);
6038 }
6039 }
6040 }
6041
6042 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
6043 String name = uri.getAuthority();
6044 ContentProviderHolder cph = getContentProviderExternal(name);
6045 ParcelFileDescriptor pfd = null;
6046 if (cph != null) {
6047 // We record the binder invoker's uid in thread-local storage before
6048 // going to the content provider to open the file. Later, in the code
6049 // that handles all permissions checks, we look for this uid and use
6050 // that rather than the Activity Manager's own uid. The effect is that
6051 // we do the check against the caller's permissions even though it looks
6052 // to the content provider like the Activity Manager itself is making
6053 // the request.
6054 sCallerIdentity.set(new Identity(
6055 Binder.getCallingPid(), Binder.getCallingUid()));
6056 try {
6057 pfd = cph.provider.openFile(uri, "r");
6058 } catch (FileNotFoundException e) {
6059 // do nothing; pfd will be returned null
6060 } finally {
6061 // Ensure that whatever happens, we clean up the identity state
6062 sCallerIdentity.remove();
6063 }
6064
6065 // We've got the fd now, so we're done with the provider.
6066 removeContentProviderExternal(name);
6067 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006068 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006069 }
6070 return pfd;
6071 }
6072
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006073 // Actually is sleeping or shutting down or whatever else in the future
6074 // is an inactive state.
6075 public boolean isSleeping() {
6076 return mSleeping || mShuttingDown;
6077 }
6078
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006079 public void goingToSleep() {
6080 synchronized(this) {
6081 mSleeping = true;
6082 mWindowManager.setEventDispatching(false);
6083
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006084 mMainStack.stopIfSleepingLocked();
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07006085
6086 // Initialize the wake times of all processes.
Dianne Hackborn287952c2010-09-22 22:34:31 -07006087 checkExcessivePowerUsageLocked(false);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07006088 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
6089 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07006090 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006091 }
6092 }
6093
Dianne Hackborn55280a92009-05-07 15:53:46 -07006094 public boolean shutdown(int timeout) {
6095 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
6096 != PackageManager.PERMISSION_GRANTED) {
6097 throw new SecurityException("Requires permission "
6098 + android.Manifest.permission.SHUTDOWN);
6099 }
6100
6101 boolean timedout = false;
6102
6103 synchronized(this) {
6104 mShuttingDown = true;
6105 mWindowManager.setEventDispatching(false);
6106
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006107 if (mMainStack.mResumedActivity != null) {
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006108 mMainStack.stopIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07006109 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006110 while (mMainStack.mResumedActivity != null
6111 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07006112 long delay = endTime - System.currentTimeMillis();
6113 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006114 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07006115 timedout = true;
6116 break;
6117 }
6118 try {
6119 this.wait();
6120 } catch (InterruptedException e) {
6121 }
6122 }
6123 }
6124 }
6125
6126 mUsageStatsService.shutdown();
6127 mBatteryStatsService.shutdown();
6128
6129 return timedout;
6130 }
6131
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006132 public final void activitySlept(IBinder token) {
6133 if (localLOGV) Slog.v(
6134 TAG, "Activity slept: token=" + token);
6135
6136 ActivityRecord r = null;
6137
6138 final long origId = Binder.clearCallingIdentity();
6139
6140 synchronized (this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07006141 r = mMainStack.isInStackLocked(token);
6142 if (r != null) {
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006143 mMainStack.activitySleptLocked(r);
6144 }
6145 }
6146
6147 Binder.restoreCallingIdentity(origId);
6148 }
6149
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006150 public void wakingUp() {
6151 synchronized(this) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006152 mWindowManager.setEventDispatching(true);
6153 mSleeping = false;
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006154 mMainStack.awakeFromSleepingLocked();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006155 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006156 }
6157 }
6158
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006159 public void stopAppSwitches() {
6160 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
6161 != PackageManager.PERMISSION_GRANTED) {
6162 throw new SecurityException("Requires permission "
6163 + android.Manifest.permission.STOP_APP_SWITCHES);
6164 }
6165
6166 synchronized(this) {
6167 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
6168 + APP_SWITCH_DELAY_TIME;
6169 mDidAppSwitch = false;
6170 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
6171 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
6172 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
6173 }
6174 }
6175
6176 public void resumeAppSwitches() {
6177 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
6178 != PackageManager.PERMISSION_GRANTED) {
6179 throw new SecurityException("Requires permission "
6180 + android.Manifest.permission.STOP_APP_SWITCHES);
6181 }
6182
6183 synchronized(this) {
6184 // Note that we don't execute any pending app switches... we will
6185 // let those wait until either the timeout, or the next start
6186 // activity request.
6187 mAppSwitchesAllowedTime = 0;
6188 }
6189 }
6190
6191 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
6192 String name) {
6193 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
6194 return true;
6195 }
6196
6197 final int perm = checkComponentPermission(
6198 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08006199 callingUid, -1, true);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006200 if (perm == PackageManager.PERMISSION_GRANTED) {
6201 return true;
6202 }
6203
Joe Onorato8a9b2202010-02-26 18:56:32 -08006204 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006205 return false;
6206 }
6207
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006208 public void setDebugApp(String packageName, boolean waitForDebugger,
6209 boolean persistent) {
6210 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
6211 "setDebugApp()");
6212
6213 // Note that this is not really thread safe if there are multiple
6214 // callers into it at the same time, but that's not a situation we
6215 // care about.
6216 if (persistent) {
6217 final ContentResolver resolver = mContext.getContentResolver();
6218 Settings.System.putString(
6219 resolver, Settings.System.DEBUG_APP,
6220 packageName);
6221 Settings.System.putInt(
6222 resolver, Settings.System.WAIT_FOR_DEBUGGER,
6223 waitForDebugger ? 1 : 0);
6224 }
6225
6226 synchronized (this) {
6227 if (!persistent) {
6228 mOrigDebugApp = mDebugApp;
6229 mOrigWaitForDebugger = mWaitForDebugger;
6230 }
6231 mDebugApp = packageName;
6232 mWaitForDebugger = waitForDebugger;
6233 mDebugTransient = !persistent;
6234 if (packageName != null) {
6235 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006236 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006237 Binder.restoreCallingIdentity(origId);
6238 }
6239 }
6240 }
6241
6242 public void setAlwaysFinish(boolean enabled) {
6243 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
6244 "setAlwaysFinish()");
6245
6246 Settings.System.putInt(
6247 mContext.getContentResolver(),
6248 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
6249
6250 synchronized (this) {
6251 mAlwaysFinishActivities = enabled;
6252 }
6253 }
6254
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006255 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006256 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006257 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006258 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006259 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006260 }
6261 }
6262
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08006263 public boolean isUserAMonkey() {
6264 // For now the fact that there is a controller implies
6265 // we have a monkey.
6266 synchronized (this) {
6267 return mController != null;
6268 }
6269 }
6270
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006271 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06006272 synchronized (this) {
6273 mWatchers.register(watcher);
6274 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006275 }
6276
6277 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06006278 synchronized (this) {
6279 mWatchers.unregister(watcher);
6280 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006281 }
6282
Jeff Sharkeya4620792011-05-20 15:29:23 -07006283 public void registerProcessObserver(IProcessObserver observer) {
6284 mProcessObservers.register(observer);
6285 }
6286
6287 public void unregisterProcessObserver(IProcessObserver observer) {
6288 mProcessObservers.unregister(observer);
6289 }
6290
Daniel Sandler69a48172010-06-23 16:29:36 -04006291 public void setImmersive(IBinder token, boolean immersive) {
6292 synchronized(this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07006293 ActivityRecord r = mMainStack.isInStackLocked(token);
6294 if (r == null) {
Daniel Sandler69a48172010-06-23 16:29:36 -04006295 throw new IllegalArgumentException();
6296 }
Daniel Sandler69a48172010-06-23 16:29:36 -04006297 r.immersive = immersive;
6298 }
6299 }
6300
6301 public boolean isImmersive(IBinder token) {
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 return r.immersive;
6308 }
6309 }
6310
6311 public boolean isTopActivityImmersive() {
6312 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006313 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Daniel Sandler69a48172010-06-23 16:29:36 -04006314 return (r != null) ? r.immersive : false;
6315 }
6316 }
6317
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006318 public final void enterSafeMode() {
6319 synchronized(this) {
6320 // It only makes sense to do this before the system is ready
6321 // and started launching other packages.
6322 if (!mSystemReady) {
6323 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006324 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006325 } catch (RemoteException e) {
6326 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006327 }
6328 }
6329 }
6330
Jeff Brownb09abc12011-01-13 21:08:27 -08006331 public final void showSafeModeOverlay() {
6332 View v = LayoutInflater.from(mContext).inflate(
6333 com.android.internal.R.layout.safe_mode, null);
6334 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
6335 lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
6336 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
6337 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
6338 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
6339 lp.format = v.getBackground().getOpacity();
6340 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
6341 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
6342 ((WindowManager)mContext.getSystemService(
6343 Context.WINDOW_SERVICE)).addView(v, lp);
6344 }
6345
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006346 public void noteWakeupAlarm(IIntentSender sender) {
6347 if (!(sender instanceof PendingIntentRecord)) {
6348 return;
6349 }
6350 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
6351 synchronized (stats) {
6352 if (mBatteryStatsService.isOnBattery()) {
6353 mBatteryStatsService.enforceCallingPermission();
6354 PendingIntentRecord rec = (PendingIntentRecord)sender;
6355 int MY_UID = Binder.getCallingUid();
6356 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
6357 BatteryStatsImpl.Uid.Pkg pkg =
6358 stats.getPackageStatsLocked(uid, rec.key.packageName);
6359 pkg.incWakeupsLocked();
6360 }
6361 }
6362 }
6363
Dianne Hackborn64825172011-03-02 21:32:58 -08006364 public boolean killPids(int[] pids, String pReason, boolean secure) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006365 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006366 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006367 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006368 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006369 // XXX Note: don't acquire main activity lock here, because the window
6370 // manager calls in with its locks held.
6371
6372 boolean killed = false;
6373 synchronized (mPidsSelfLocked) {
6374 int[] types = new int[pids.length];
6375 int worstType = 0;
6376 for (int i=0; i<pids.length; i++) {
6377 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6378 if (proc != null) {
6379 int type = proc.setAdj;
6380 types[i] = type;
6381 if (type > worstType) {
6382 worstType = type;
6383 }
6384 }
6385 }
6386
Dianne Hackborn64825172011-03-02 21:32:58 -08006387 // If the worst oom_adj is somewhere in the hidden proc LRU range,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006388 // then constrain it so we will kill all hidden procs.
6389 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
6390 worstType = HIDDEN_APP_MIN_ADJ;
6391 }
Dianne Hackborn64825172011-03-02 21:32:58 -08006392
6393 // If this is not a secure call, don't let it kill processes that
6394 // are important.
6395 if (!secure && worstType < SECONDARY_SERVER_ADJ) {
6396 worstType = SECONDARY_SERVER_ADJ;
6397 }
6398
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006399 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006400 for (int i=0; i<pids.length; i++) {
6401 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6402 if (proc == null) {
6403 continue;
6404 }
6405 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006406 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07006407 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006408 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
6409 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006410 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006411 proc.killedBackground = true;
6412 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006413 }
6414 }
6415 }
6416 return killed;
6417 }
6418
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006419 public final void startRunning(String pkg, String cls, String action,
6420 String data) {
6421 synchronized(this) {
6422 if (mStartRunning) {
6423 return;
6424 }
6425 mStartRunning = true;
6426 mTopComponent = pkg != null && cls != null
6427 ? new ComponentName(pkg, cls) : null;
6428 mTopAction = action != null ? action : Intent.ACTION_MAIN;
6429 mTopData = data;
6430 if (!mSystemReady) {
6431 return;
6432 }
6433 }
6434
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006435 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006436 }
6437
6438 private void retrieveSettings() {
6439 final ContentResolver resolver = mContext.getContentResolver();
6440 String debugApp = Settings.System.getString(
6441 resolver, Settings.System.DEBUG_APP);
6442 boolean waitForDebugger = Settings.System.getInt(
6443 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
6444 boolean alwaysFinishActivities = Settings.System.getInt(
6445 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
6446
6447 Configuration configuration = new Configuration();
6448 Settings.System.getConfiguration(resolver, configuration);
6449
6450 synchronized (this) {
6451 mDebugApp = mOrigDebugApp = debugApp;
6452 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
6453 mAlwaysFinishActivities = alwaysFinishActivities;
6454 // This happens before any activities are started, so we can
6455 // change mConfiguration in-place.
6456 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08006457 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006458 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006459 }
6460 }
6461
6462 public boolean testIsSystemReady() {
6463 // no need to synchronize(this) just to read & return the value
6464 return mSystemReady;
6465 }
6466
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006467 private static File getCalledPreBootReceiversFile() {
6468 File dataDir = Environment.getDataDirectory();
6469 File systemDir = new File(dataDir, "system");
6470 File fname = new File(systemDir, "called_pre_boots.dat");
6471 return fname;
6472 }
6473
6474 private static ArrayList<ComponentName> readLastDonePreBootReceivers() {
6475 ArrayList<ComponentName> lastDoneReceivers = new ArrayList<ComponentName>();
6476 File file = getCalledPreBootReceiversFile();
6477 FileInputStream fis = null;
6478 try {
6479 fis = new FileInputStream(file);
6480 DataInputStream dis = new DataInputStream(new BufferedInputStream(fis, 2048));
6481 int vers = dis.readInt();
6482 String codename = dis.readUTF();
6483 if (vers == android.os.Build.VERSION.SDK_INT
6484 && codename.equals(android.os.Build.VERSION.CODENAME)) {
6485 int num = dis.readInt();
6486 while (num > 0) {
6487 num--;
6488 String pkg = dis.readUTF();
6489 String cls = dis.readUTF();
6490 lastDoneReceivers.add(new ComponentName(pkg, cls));
6491 }
6492 }
6493 } catch (FileNotFoundException e) {
6494 } catch (IOException e) {
6495 Slog.w(TAG, "Failure reading last done pre-boot receivers", e);
6496 } finally {
6497 if (fis != null) {
6498 try {
6499 fis.close();
6500 } catch (IOException e) {
6501 }
6502 }
6503 }
6504 return lastDoneReceivers;
6505 }
6506
6507 private static void writeLastDonePreBootReceivers(ArrayList<ComponentName> list) {
6508 File file = getCalledPreBootReceiversFile();
6509 FileOutputStream fos = null;
6510 DataOutputStream dos = null;
6511 try {
6512 Slog.i(TAG, "Writing new set of last done pre-boot receivers...");
6513 fos = new FileOutputStream(file);
6514 dos = new DataOutputStream(new BufferedOutputStream(fos, 2048));
6515 dos.writeInt(android.os.Build.VERSION.SDK_INT);
6516 dos.writeUTF(android.os.Build.VERSION.CODENAME);
6517 dos.writeInt(list.size());
6518 for (int i=0; i<list.size(); i++) {
6519 dos.writeUTF(list.get(i).getPackageName());
6520 dos.writeUTF(list.get(i).getClassName());
6521 }
6522 } catch (IOException e) {
6523 Slog.w(TAG, "Failure writing last done pre-boot receivers", e);
6524 file.delete();
6525 } finally {
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07006526 FileUtils.sync(fos);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006527 if (dos != null) {
6528 try {
6529 dos.close();
6530 } catch (IOException e) {
6531 // TODO Auto-generated catch block
6532 e.printStackTrace();
6533 }
6534 }
6535 }
6536 }
6537
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006538 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006539 synchronized(this) {
6540 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006541 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006542 return;
6543 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006544
6545 // Check to see if there are any update receivers to run.
6546 if (!mDidUpdate) {
6547 if (mWaitingUpdate) {
6548 return;
6549 }
6550 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
6551 List<ResolveInfo> ris = null;
6552 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006553 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006554 intent, null, 0);
6555 } catch (RemoteException e) {
6556 }
6557 if (ris != null) {
6558 for (int i=ris.size()-1; i>=0; i--) {
6559 if ((ris.get(i).activityInfo.applicationInfo.flags
6560 &ApplicationInfo.FLAG_SYSTEM) == 0) {
6561 ris.remove(i);
6562 }
6563 }
6564 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006565
6566 ArrayList<ComponentName> lastDoneReceivers = readLastDonePreBootReceivers();
6567
6568 final ArrayList<ComponentName> doneReceivers = new ArrayList<ComponentName>();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006569 for (int i=0; i<ris.size(); i++) {
6570 ActivityInfo ai = ris.get(i).activityInfo;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006571 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6572 if (lastDoneReceivers.contains(comp)) {
6573 ris.remove(i);
6574 i--;
6575 }
6576 }
6577
6578 for (int i=0; i<ris.size(); i++) {
6579 ActivityInfo ai = ris.get(i).activityInfo;
6580 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6581 doneReceivers.add(comp);
6582 intent.setComponent(comp);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006583 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08006584 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006585 finisher = new IIntentReceiver.Stub() {
6586 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07006587 String data, Bundle extras, boolean ordered,
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006588 boolean sticky) {
6589 // The raw IIntentReceiver interface is called
6590 // with the AM lock held, so redispatch to
6591 // execute our code without the lock.
6592 mHandler.post(new Runnable() {
6593 public void run() {
6594 synchronized (ActivityManagerService.this) {
6595 mDidUpdate = true;
6596 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006597 writeLastDonePreBootReceivers(doneReceivers);
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006598 systemReady(goingCallback);
6599 }
6600 });
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006601 }
6602 };
6603 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006604 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006605 broadcastIntentLocked(null, null, intent, null, finisher,
6606 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08006607 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006608 mWaitingUpdate = true;
6609 }
6610 }
6611 }
6612 if (mWaitingUpdate) {
6613 return;
6614 }
6615 mDidUpdate = true;
6616 }
6617
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006618 mSystemReady = true;
6619 if (!mStartRunning) {
6620 return;
6621 }
6622 }
6623
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006624 ArrayList<ProcessRecord> procsToKill = null;
6625 synchronized(mPidsSelfLocked) {
6626 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
6627 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
6628 if (!isAllowedWhileBooting(proc.info)){
6629 if (procsToKill == null) {
6630 procsToKill = new ArrayList<ProcessRecord>();
6631 }
6632 procsToKill.add(proc);
6633 }
6634 }
6635 }
6636
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006637 synchronized(this) {
6638 if (procsToKill != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006639 for (int i=procsToKill.size()-1; i>=0; i--) {
6640 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08006641 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006642 removeProcessLocked(proc, true);
6643 }
6644 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006645
6646 // Now that we have cleaned up any update processes, we
6647 // are ready to start launching real processes and know that
6648 // we won't trample on them any more.
6649 mProcessesReady = true;
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006650 }
6651
Joe Onorato8a9b2202010-02-26 18:56:32 -08006652 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006653 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006654 SystemClock.uptimeMillis());
6655
6656 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006657 // Make sure we have no pre-ready processes sitting around.
6658
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006659 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
6660 ResolveInfo ri = mContext.getPackageManager()
6661 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07006662 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006663 CharSequence errorMsg = null;
6664 if (ri != null) {
6665 ActivityInfo ai = ri.activityInfo;
6666 ApplicationInfo app = ai.applicationInfo;
6667 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
6668 mTopAction = Intent.ACTION_FACTORY_TEST;
6669 mTopData = null;
6670 mTopComponent = new ComponentName(app.packageName,
6671 ai.name);
6672 } else {
6673 errorMsg = mContext.getResources().getText(
6674 com.android.internal.R.string.factorytest_not_system);
6675 }
6676 } else {
6677 errorMsg = mContext.getResources().getText(
6678 com.android.internal.R.string.factorytest_no_action);
6679 }
6680 if (errorMsg != null) {
6681 mTopAction = null;
6682 mTopData = null;
6683 mTopComponent = null;
6684 Message msg = Message.obtain();
6685 msg.what = SHOW_FACTORY_ERROR_MSG;
6686 msg.getData().putCharSequence("msg", errorMsg);
6687 mHandler.sendMessage(msg);
6688 }
6689 }
6690 }
6691
6692 retrieveSettings();
6693
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006694 if (goingCallback != null) goingCallback.run();
6695
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006696 synchronized (this) {
6697 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
6698 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006699 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07006700 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006701 if (apps != null) {
6702 int N = apps.size();
6703 int i;
6704 for (i=0; i<N; i++) {
6705 ApplicationInfo info
6706 = (ApplicationInfo)apps.get(i);
6707 if (info != null &&
6708 !info.packageName.equals("android")) {
6709 addAppLocked(info);
6710 }
6711 }
6712 }
6713 } catch (RemoteException ex) {
6714 // pm is in same process, this will never happen.
6715 }
6716 }
6717
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006718 // Start up initial activity.
6719 mBooting = true;
6720
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006721 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006722 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006723 Message msg = Message.obtain();
6724 msg.what = SHOW_UID_ERROR_MSG;
6725 mHandler.sendMessage(msg);
6726 }
6727 } catch (RemoteException e) {
6728 }
6729
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006730 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006731 }
6732 }
6733
Dan Egnorb7f03672009-12-09 16:22:32 -08006734 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006735 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006736 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006737 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006738 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006739 startAppProblemLocked(app);
6740 app.stopFreezingAllLocked();
6741 return handleAppCrashLocked(app);
6742 }
6743
Dan Egnorb7f03672009-12-09 16:22:32 -08006744 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006745 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006746 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006747 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006748 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
6749 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006750 startAppProblemLocked(app);
6751 app.stopFreezingAllLocked();
6752 }
6753
6754 /**
6755 * Generate a process error record, suitable for attachment to a ProcessRecord.
6756 *
6757 * @param app The ProcessRecord in which the error occurred.
6758 * @param condition Crashing, Application Not Responding, etc. Values are defined in
6759 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08006760 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006761 * @param shortMsg Short message describing the crash.
6762 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08006763 * @param stackTrace Full crash stack trace, may be null.
6764 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006765 * @return Returns a fully-formed AppErrorStateInfo record.
6766 */
6767 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006768 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006769 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08006770
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006771 report.condition = condition;
6772 report.processName = app.processName;
6773 report.pid = app.pid;
6774 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08006775 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006776 report.shortMsg = shortMsg;
6777 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08006778 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006779
6780 return report;
6781 }
6782
Dan Egnor42471dd2010-01-07 17:25:22 -08006783 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006784 synchronized (this) {
6785 app.crashing = false;
6786 app.crashingReport = null;
6787 app.notResponding = false;
6788 app.notRespondingReport = null;
6789 if (app.anrDialog == fromDialog) {
6790 app.anrDialog = null;
6791 }
6792 if (app.waitDialog == fromDialog) {
6793 app.waitDialog = null;
6794 }
6795 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08006796 handleAppCrashLocked(app);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07006797 Slog.i(ActivityManagerService.TAG, "Killing " + app + ": user's request");
Dianne Hackborn8633e682010-04-22 16:03:41 -07006798 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
6799 app.processName, app.setAdj, "user's request after error");
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07006800 Process.killProcessQuiet(app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006801 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006802 }
6803 }
Dan Egnor42471dd2010-01-07 17:25:22 -08006804
Dan Egnorb7f03672009-12-09 16:22:32 -08006805 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006806 long now = SystemClock.uptimeMillis();
6807
6808 Long crashTime = mProcessCrashTimes.get(app.info.processName,
6809 app.info.uid);
6810 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
6811 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006812 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006813 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006814 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006815 app.info.processName, app.info.uid);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006816 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
6817 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006818 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006819 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006820 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006821 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006822 }
6823 }
6824 if (!app.persistent) {
Dianne Hackborn070783f2010-12-29 16:46:28 -08006825 // Don't let services in this process be restarted and potentially
6826 // annoy the user repeatedly. Unless it is persistent, since those
6827 // processes run critical code.
6828 killServicesLocked(app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006829 // We don't want to start this process again until the user
6830 // explicitly does so... but for persistent process, we really
6831 // need to keep it running. If a persistent process is actually
6832 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08006833 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006834 app.info.processName);
6835 mBadProcesses.put(app.info.processName, app.info.uid, now);
6836 app.bad = true;
6837 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
6838 app.removed = true;
6839 removeProcessLocked(app, false);
Dianne Hackborncb44d962011-03-10 17:02:27 -08006840 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006841 return false;
6842 }
Dianne Hackborncb44d962011-03-10 17:02:27 -08006843 mMainStack.resumeTopActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006844 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006845 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006846 if (r.app == app) {
6847 // If the top running activity is from this crashing
6848 // process, then terminate it to avoid getting in a loop.
6849 Slog.w(TAG, " Force finishing activity "
6850 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006851 int index = mMainStack.indexOfTokenLocked(r);
6852 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006853 Activity.RESULT_CANCELED, null, "crashed");
Dianne Hackborn070783f2010-12-29 16:46:28 -08006854 // Also terminate any activities below it that aren't yet
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006855 // stopped, to avoid a situation where one will get
6856 // re-start our crashing activity once it gets resumed again.
6857 index--;
6858 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006859 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006860 if (r.state == ActivityState.RESUMED
6861 || r.state == ActivityState.PAUSING
6862 || r.state == ActivityState.PAUSED) {
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -08006863 if (!r.isHomeActivity || mHomeProcess != r.app) {
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006864 Slog.w(TAG, " Force finishing activity "
6865 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006866 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006867 Activity.RESULT_CANCELED, null, "crashed");
6868 }
6869 }
6870 }
6871 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006872 }
6873
6874 // Bump up the crash count of any services currently running in the proc.
6875 if (app.services.size() != 0) {
6876 // Any services running in the application need to be placed
6877 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07006878 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006879 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006880 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006881 sr.crashCount++;
6882 }
6883 }
Mattias Larssona4fd0072010-06-22 22:37:03 +02006884
6885 // If the crashing process is what we consider to be the "home process" and it has been
6886 // replaced by a third-party app, clear the package preferred activities from packages
6887 // with a home activity running in the process to prevent a repeatedly crashing app
6888 // from blocking the user to manually clear the list.
6889 if (app == mHomeProcess && mHomeProcess.activities.size() > 0
6890 && (mHomeProcess.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
6891 Iterator it = mHomeProcess.activities.iterator();
6892 while (it.hasNext()) {
Jean-Baptiste Queru5ea89f72010-07-30 09:30:31 -07006893 ActivityRecord r = (ActivityRecord)it.next();
Mattias Larssona4fd0072010-06-22 22:37:03 +02006894 if (r.isHomeActivity) {
6895 Log.i(TAG, "Clearing package preferred activities from " + r.packageName);
6896 try {
6897 ActivityThread.getPackageManager()
6898 .clearPackagePreferredActivities(r.packageName);
6899 } catch (RemoteException c) {
6900 // pm is in same process, this will never happen.
6901 }
6902 }
6903 }
6904 }
6905
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006906 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
6907 return true;
6908 }
6909
6910 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006911 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
6912 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006913 skipCurrentReceiverLocked(app);
6914 }
6915
6916 void skipCurrentReceiverLocked(ProcessRecord app) {
6917 boolean reschedule = false;
6918 BroadcastRecord r = app.curReceiver;
6919 if (r != null) {
6920 // The current broadcast is waiting for this app's receiver
6921 // to be finished. Looks like that's not going to happen, so
6922 // let the broadcast continue.
Jeff Brown4d94a762010-09-23 11:33:28 -07006923 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006924 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6925 r.resultExtras, r.resultAbort, true);
6926 reschedule = true;
6927 }
6928 r = mPendingBroadcast;
6929 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006930 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006931 "skip & discard pending app " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -07006932 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006933 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6934 r.resultExtras, r.resultAbort, true);
6935 reschedule = true;
6936 }
6937 if (reschedule) {
6938 scheduleBroadcastsLocked();
6939 }
6940 }
6941
Dan Egnor60d87622009-12-16 16:32:58 -08006942 /**
6943 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
6944 * The application process will exit immediately after this call returns.
6945 * @param app object of the crashing app, null for the system server
6946 * @param crashInfo describing the exception
6947 */
6948 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
Dianne Hackborncb44d962011-03-10 17:02:27 -08006949 ProcessRecord r = findAppProcess(app, "Crash");
Dan Egnor60d87622009-12-16 16:32:58 -08006950
6951 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
6952 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006953 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006954 crashInfo.exceptionClassName,
6955 crashInfo.exceptionMessage,
6956 crashInfo.throwFileName,
6957 crashInfo.throwLineNumber);
6958
Dan Egnor42471dd2010-01-07 17:25:22 -08006959 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006960
6961 crashApplication(r, crashInfo);
6962 }
6963
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006964 public void handleApplicationStrictModeViolation(
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006965 IBinder app,
6966 int violationMask,
6967 StrictMode.ViolationInfo info) {
Dianne Hackborncb44d962011-03-10 17:02:27 -08006968 ProcessRecord r = findAppProcess(app, "StrictMode");
6969 if (r == null) {
6970 return;
6971 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006972
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006973 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -08006974 Integer stackFingerprint = info.hashCode();
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006975 boolean logIt = true;
6976 synchronized (mAlreadyLoggedViolatedStacks) {
6977 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
6978 logIt = false;
6979 // TODO: sub-sample into EventLog for these, with
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006980 // the info.durationMillis? Then we'd get
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006981 // the relative pain numbers, without logging all
6982 // the stack traces repeatedly. We'd want to do
6983 // likewise in the client code, which also does
6984 // dup suppression, before the Binder call.
6985 } else {
6986 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
6987 mAlreadyLoggedViolatedStacks.clear();
6988 }
6989 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
6990 }
6991 }
6992 if (logIt) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006993 logStrictModeViolationToDropBox(r, info);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006994 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006995 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006996
6997 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
6998 AppErrorResult result = new AppErrorResult();
6999 synchronized (this) {
7000 final long origId = Binder.clearCallingIdentity();
7001
7002 Message msg = Message.obtain();
7003 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
7004 HashMap<String, Object> data = new HashMap<String, Object>();
7005 data.put("result", result);
7006 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07007007 data.put("violationMask", violationMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007008 data.put("info", info);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07007009 msg.obj = data;
7010 mHandler.sendMessage(msg);
7011
7012 Binder.restoreCallingIdentity(origId);
7013 }
7014 int res = result.get();
Dianne Hackbornb424b632010-08-18 15:59:05 -07007015 Slog.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07007016 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07007017 }
7018
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007019 // Depending on the policy in effect, there could be a bunch of
7020 // these in quick succession so we try to batch these together to
7021 // minimize disk writes, number of dropbox entries, and maximize
7022 // compression, by having more fewer, larger records.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007023 private void logStrictModeViolationToDropBox(
7024 ProcessRecord process,
7025 StrictMode.ViolationInfo info) {
7026 if (info == null) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007027 return;
7028 }
7029 final boolean isSystemApp = process == null ||
7030 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
7031 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
7032 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
7033 final DropBoxManager dbox = (DropBoxManager)
7034 mContext.getSystemService(Context.DROPBOX_SERVICE);
7035
7036 // Exit early if the dropbox isn't configured to accept this report type.
7037 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
7038
7039 boolean bufferWasEmpty;
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007040 boolean needsFlush;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007041 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
7042 synchronized (sb) {
7043 bufferWasEmpty = sb.length() == 0;
7044 appendDropBoxProcessHeaders(process, sb);
7045 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
7046 sb.append("System-App: ").append(isSystemApp).append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007047 sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
7048 if (info.violationNumThisLoop != 0) {
7049 sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
7050 }
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07007051 if (info.numAnimationsRunning != 0) {
7052 sb.append("Animations-Running: ").append(info.numAnimationsRunning).append("\n");
7053 }
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07007054 if (info.broadcastIntentAction != null) {
7055 sb.append("Broadcast-Intent-Action: ").append(info.broadcastIntentAction).append("\n");
7056 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08007057 if (info.durationMillis != -1) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007058 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007059 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08007060 if (info.numInstances != -1) {
7061 sb.append("Instance-Count: ").append(info.numInstances).append("\n");
7062 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08007063 if (info.tags != null) {
7064 for (String tag : info.tags) {
7065 sb.append("Span-Tag: ").append(tag).append("\n");
7066 }
7067 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007068 sb.append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007069 if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
7070 sb.append(info.crashInfo.stackTrace);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007071 }
7072 sb.append("\n");
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007073
7074 // Only buffer up to ~64k. Various logging bits truncate
7075 // things at 128k.
7076 needsFlush = (sb.length() > 64 * 1024);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007077 }
7078
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007079 // Flush immediately if the buffer's grown too large, or this
7080 // is a non-system app. Non-system apps are isolated with a
7081 // different tag & policy and not batched.
7082 //
7083 // Batching is useful during internal testing with
7084 // StrictMode settings turned up high. Without batching,
7085 // thousands of separate files could be created on boot.
7086 if (!isSystemApp || needsFlush) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007087 new Thread("Error dump: " + dropboxTag) {
7088 @Override
7089 public void run() {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007090 String report;
7091 synchronized (sb) {
7092 report = sb.toString();
7093 sb.delete(0, sb.length());
7094 sb.trimToSize();
7095 }
7096 if (report.length() != 0) {
7097 dbox.addText(dropboxTag, report);
7098 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007099 }
7100 }.start();
7101 return;
7102 }
7103
7104 // System app batching:
7105 if (!bufferWasEmpty) {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007106 // An existing dropbox-writing thread is outstanding, so
7107 // we don't need to start it up. The existing thread will
7108 // catch the buffer appends we just did.
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007109 return;
7110 }
7111
7112 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
7113 // (After this point, we shouldn't access AMS internal data structures.)
7114 new Thread("Error dump: " + dropboxTag) {
7115 @Override
7116 public void run() {
7117 // 5 second sleep to let stacks arrive and be batched together
7118 try {
7119 Thread.sleep(5000); // 5 seconds
7120 } catch (InterruptedException e) {}
7121
7122 String errorReport;
7123 synchronized (mStrictModeBuffer) {
7124 errorReport = mStrictModeBuffer.toString();
7125 if (errorReport.length() == 0) {
7126 return;
7127 }
7128 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
7129 mStrictModeBuffer.trimToSize();
7130 }
7131 dbox.addText(dropboxTag, errorReport);
7132 }
7133 }.start();
7134 }
7135
Dan Egnor60d87622009-12-16 16:32:58 -08007136 /**
7137 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
7138 * @param app object of the crashing app, null for the system server
7139 * @param tag reported by the caller
7140 * @param crashInfo describing the context of the error
7141 * @return true if the process should exit immediately (WTF is fatal)
7142 */
7143 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08007144 ApplicationErrorReport.CrashInfo crashInfo) {
Dianne Hackborncb44d962011-03-10 17:02:27 -08007145 ProcessRecord r = findAppProcess(app, "WTF");
Dan Egnor60d87622009-12-16 16:32:58 -08007146
7147 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
7148 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08007149 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08007150 tag, crashInfo.exceptionMessage);
7151
Dan Egnor42471dd2010-01-07 17:25:22 -08007152 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08007153
Dianne Hackborn1ab43772011-03-15 14:38:02 -07007154 if (r != null && r.pid != Process.myPid() &&
7155 Settings.Secure.getInt(mContext.getContentResolver(),
7156 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08007157 crashApplication(r, crashInfo);
7158 return true;
7159 } else {
7160 return false;
7161 }
7162 }
7163
7164 /**
7165 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
7166 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
7167 */
Dianne Hackborncb44d962011-03-10 17:02:27 -08007168 private ProcessRecord findAppProcess(IBinder app, String reason) {
Dan Egnor60d87622009-12-16 16:32:58 -08007169 if (app == null) {
7170 return null;
7171 }
7172
7173 synchronized (this) {
7174 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
7175 final int NA = apps.size();
7176 for (int ia=0; ia<NA; ia++) {
7177 ProcessRecord p = apps.valueAt(ia);
7178 if (p.thread != null && p.thread.asBinder() == app) {
7179 return p;
7180 }
7181 }
7182 }
7183
Dianne Hackborncb44d962011-03-10 17:02:27 -08007184 Slog.w(TAG, "Can't find mystery application for " + reason
7185 + " from pid=" + Binder.getCallingPid()
7186 + " uid=" + Binder.getCallingUid() + ": " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08007187 return null;
7188 }
7189 }
7190
7191 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007192 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
7193 * to append various headers to the dropbox log text.
Dan Egnor60d87622009-12-16 16:32:58 -08007194 */
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07007195 private void appendDropBoxProcessHeaders(ProcessRecord process, StringBuilder sb) {
Vairavan Srinivasan68a4e0a2011-02-14 20:45:59 -08007196 // Watchdog thread ends up invoking this function (with
7197 // a null ProcessRecord) to add the stack file to dropbox.
7198 // Do not acquire a lock on this (am) in such cases, as it
7199 // could cause a potential deadlock, if and when watchdog
7200 // is invoked due to unavailability of lock on am and it
7201 // would prevent watchdog from killing system_server.
7202 if (process == null) {
7203 sb.append("Process: system_server\n");
7204 return;
7205 }
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07007206 // Note: ProcessRecord 'process' is guarded by the service
7207 // instance. (notably process.pkgList, which could otherwise change
7208 // concurrently during execution of this method)
7209 synchronized (this) {
Vairavan Srinivasan68a4e0a2011-02-14 20:45:59 -08007210 if (process.pid == MY_PID) {
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07007211 sb.append("Process: system_server\n");
7212 } else {
7213 sb.append("Process: ").append(process.processName).append("\n");
7214 }
Dan Egnora455d192010-03-12 08:52:28 -08007215 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007216 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08007217 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
7218 for (String pkg : process.pkgList) {
7219 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08007220 try {
Dan Egnora455d192010-03-12 08:52:28 -08007221 PackageInfo pi = pm.getPackageInfo(pkg, 0);
7222 if (pi != null) {
7223 sb.append(" v").append(pi.versionCode);
7224 if (pi.versionName != null) {
7225 sb.append(" (").append(pi.versionName).append(")");
7226 }
7227 }
7228 } catch (RemoteException e) {
7229 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08007230 }
Dan Egnora455d192010-03-12 08:52:28 -08007231 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08007232 }
Dan Egnora455d192010-03-12 08:52:28 -08007233 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007234 }
7235
7236 private static String processClass(ProcessRecord process) {
7237 if (process == null || process.pid == MY_PID) {
7238 return "system_server";
7239 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
7240 return "system_app";
7241 } else {
7242 return "data_app";
7243 }
7244 }
7245
7246 /**
7247 * Write a description of an error (crash, WTF, ANR) to the drop box.
7248 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
7249 * @param process which caused the error, null means the system server
7250 * @param activity which triggered the error, null if unknown
7251 * @param parent activity related to the error, null if unknown
7252 * @param subject line related to the error, null if absent
7253 * @param report in long form describing the error, null if absent
7254 * @param logFile to include in the report, null if none
7255 * @param crashInfo giving an application stack trace, null if absent
7256 */
7257 public void addErrorToDropBox(String eventType,
7258 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
7259 final String report, final File logFile,
7260 final ApplicationErrorReport.CrashInfo crashInfo) {
7261 // NOTE -- this must never acquire the ActivityManagerService lock,
7262 // otherwise the watchdog may be prevented from resetting the system.
7263
7264 final String dropboxTag = processClass(process) + "_" + eventType;
7265 final DropBoxManager dbox = (DropBoxManager)
7266 mContext.getSystemService(Context.DROPBOX_SERVICE);
7267
7268 // Exit early if the dropbox isn't configured to accept this report type.
7269 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
7270
7271 final StringBuilder sb = new StringBuilder(1024);
7272 appendDropBoxProcessHeaders(process, sb);
Dan Egnora455d192010-03-12 08:52:28 -08007273 if (activity != null) {
7274 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
7275 }
7276 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
7277 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
7278 }
7279 if (parent != null && parent != activity) {
7280 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
7281 }
7282 if (subject != null) {
7283 sb.append("Subject: ").append(subject).append("\n");
7284 }
7285 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
Christian Lindeberg03d2ca62010-09-28 14:52:20 +02007286 if (Debug.isDebuggerConnected()) {
7287 sb.append("Debugger: Connected\n");
7288 }
Dan Egnora455d192010-03-12 08:52:28 -08007289 sb.append("\n");
7290
7291 // Do the rest in a worker thread to avoid blocking the caller on I/O
7292 // (After this point, we shouldn't access AMS internal data structures.)
7293 Thread worker = new Thread("Error dump: " + dropboxTag) {
7294 @Override
7295 public void run() {
7296 if (report != null) {
7297 sb.append(report);
7298 }
7299 if (logFile != null) {
7300 try {
7301 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
7302 } catch (IOException e) {
7303 Slog.e(TAG, "Error reading " + logFile, e);
7304 }
7305 }
7306 if (crashInfo != null && crashInfo.stackTrace != null) {
7307 sb.append(crashInfo.stackTrace);
7308 }
7309
7310 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
7311 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
7312 if (lines > 0) {
7313 sb.append("\n");
7314
7315 // Merge several logcat streams, and take the last N lines
7316 InputStreamReader input = null;
7317 try {
7318 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
7319 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
7320 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
7321
7322 try { logcat.getOutputStream().close(); } catch (IOException e) {}
7323 try { logcat.getErrorStream().close(); } catch (IOException e) {}
7324 input = new InputStreamReader(logcat.getInputStream());
7325
7326 int num;
7327 char[] buf = new char[8192];
7328 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
7329 } catch (IOException e) {
7330 Slog.e(TAG, "Error running logcat", e);
7331 } finally {
7332 if (input != null) try { input.close(); } catch (IOException e) {}
7333 }
7334 }
7335
7336 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08007337 }
Dan Egnora455d192010-03-12 08:52:28 -08007338 };
7339
7340 if (process == null || process.pid == MY_PID) {
7341 worker.run(); // We may be about to die -- need to run this synchronously
7342 } else {
7343 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08007344 }
7345 }
7346
7347 /**
7348 * Bring up the "unexpected error" dialog box for a crashing app.
7349 * Deal with edge cases (intercepts from instrumented applications,
7350 * ActivityController, error intent receivers, that sort of thing).
7351 * @param r the application crashing
7352 * @param crashInfo describing the failure
7353 */
7354 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007355 long timeMillis = System.currentTimeMillis();
7356 String shortMsg = crashInfo.exceptionClassName;
7357 String longMsg = crashInfo.exceptionMessage;
7358 String stackTrace = crashInfo.stackTrace;
7359 if (shortMsg != null && longMsg != null) {
7360 longMsg = shortMsg + ": " + longMsg;
7361 } else if (shortMsg != null) {
7362 longMsg = shortMsg;
7363 }
7364
Dan Egnor60d87622009-12-16 16:32:58 -08007365 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007366 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007367 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007368 try {
7369 String name = r != null ? r.processName : null;
7370 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08007371 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08007372 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007373 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007374 + " at watcher's request");
7375 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08007376 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007377 }
7378 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007379 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007380 }
7381 }
7382
7383 final long origId = Binder.clearCallingIdentity();
7384
7385 // If this process is running instrumentation, finish it.
7386 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007387 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007388 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08007389 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
7390 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007391 Bundle info = new Bundle();
7392 info.putString("shortMsg", shortMsg);
7393 info.putString("longMsg", longMsg);
7394 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
7395 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007396 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007397 }
7398
Dan Egnor60d87622009-12-16 16:32:58 -08007399 // If we can't identify the process or it's already exceeded its crash quota,
7400 // quit right away without showing a crash dialog.
7401 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007402 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007403 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007404 }
7405
7406 Message msg = Message.obtain();
7407 msg.what = SHOW_ERROR_MSG;
7408 HashMap data = new HashMap();
7409 data.put("result", result);
7410 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007411 msg.obj = data;
7412 mHandler.sendMessage(msg);
7413
7414 Binder.restoreCallingIdentity(origId);
7415 }
7416
7417 int res = result.get();
7418
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007419 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007420 synchronized (this) {
7421 if (r != null) {
7422 mProcessCrashTimes.put(r.info.processName, r.info.uid,
7423 SystemClock.uptimeMillis());
7424 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007425 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007426 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007427 }
7428 }
7429
7430 if (appErrorIntent != null) {
7431 try {
7432 mContext.startActivity(appErrorIntent);
7433 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007434 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007435 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007436 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007437 }
Dan Egnorb7f03672009-12-09 16:22:32 -08007438
7439 Intent createAppErrorIntentLocked(ProcessRecord r,
7440 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
7441 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007442 if (report == null) {
7443 return null;
7444 }
7445 Intent result = new Intent(Intent.ACTION_APP_ERROR);
7446 result.setComponent(r.errorReportReceiver);
7447 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
7448 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
7449 return result;
7450 }
7451
Dan Egnorb7f03672009-12-09 16:22:32 -08007452 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
7453 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007454 if (r.errorReportReceiver == null) {
7455 return null;
7456 }
7457
7458 if (!r.crashing && !r.notResponding) {
7459 return null;
7460 }
7461
Dan Egnorb7f03672009-12-09 16:22:32 -08007462 ApplicationErrorReport report = new ApplicationErrorReport();
7463 report.packageName = r.info.packageName;
7464 report.installerPackageName = r.errorReportReceiver.getPackageName();
7465 report.processName = r.processName;
7466 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01007467 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007468
Dan Egnorb7f03672009-12-09 16:22:32 -08007469 if (r.crashing) {
7470 report.type = ApplicationErrorReport.TYPE_CRASH;
7471 report.crashInfo = crashInfo;
7472 } else if (r.notResponding) {
7473 report.type = ApplicationErrorReport.TYPE_ANR;
7474 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007475
Dan Egnorb7f03672009-12-09 16:22:32 -08007476 report.anrInfo.activity = r.notRespondingReport.tag;
7477 report.anrInfo.cause = r.notRespondingReport.shortMsg;
7478 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007479 }
7480
Dan Egnorb7f03672009-12-09 16:22:32 -08007481 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007482 }
7483
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007484 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
7485 // assume our apps are happy - lazy create the list
7486 List<ActivityManager.ProcessErrorStateInfo> errList = null;
7487
7488 synchronized (this) {
7489
7490 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007491 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7492 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007493 if ((app.thread != null) && (app.crashing || app.notResponding)) {
7494 // This one's in trouble, so we'll generate a report for it
7495 // crashes are higher priority (in case there's a crash *and* an anr)
7496 ActivityManager.ProcessErrorStateInfo report = null;
7497 if (app.crashing) {
7498 report = app.crashingReport;
7499 } else if (app.notResponding) {
7500 report = app.notRespondingReport;
7501 }
7502
7503 if (report != null) {
7504 if (errList == null) {
7505 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
7506 }
7507 errList.add(report);
7508 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007509 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007510 " crashing = " + app.crashing +
7511 " notResponding = " + app.notResponding);
7512 }
7513 }
7514 }
7515 }
7516
7517 return errList;
7518 }
7519
7520 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
7521 // Lazy instantiation of list
7522 List<ActivityManager.RunningAppProcessInfo> runList = null;
7523 synchronized (this) {
7524 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007525 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7526 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007527 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
7528 // Generate process state info for running application
7529 ActivityManager.RunningAppProcessInfo currApp =
7530 new ActivityManager.RunningAppProcessInfo(app.processName,
7531 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07007532 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007533 if (mHeavyWeightProcess == app) {
Dianne Hackborn482566e2010-09-03 12:51:28 -07007534 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007535 }
Dianne Hackborn42499172010-10-15 18:45:07 -07007536 if (app.persistent) {
7537 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_PERSISTENT;
7538 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007539 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007540 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007541 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
7542 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
7543 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08007544 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
7545 } else if (adj >= HOME_APP_ADJ) {
7546 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
7547 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007548 } else if (adj >= SECONDARY_SERVER_ADJ) {
7549 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007550 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackborn5383f502010-10-22 12:59:20 -07007551 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007552 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
7553 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007554 } else if (adj >= VISIBLE_APP_ADJ) {
7555 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
7556 } else {
7557 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
7558 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007559 currApp.importanceReasonCode = app.adjTypeCode;
7560 if (app.adjSource instanceof ProcessRecord) {
7561 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007562 } else if (app.adjSource instanceof ActivityRecord) {
7563 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007564 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
7565 }
7566 if (app.adjTarget instanceof ComponentName) {
7567 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
7568 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007569 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007570 // + " lru=" + currApp.lru);
7571 if (runList == null) {
7572 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
7573 }
7574 runList.add(currApp);
7575 }
7576 }
7577 }
7578 return runList;
7579 }
7580
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007581 public List<ApplicationInfo> getRunningExternalApplications() {
7582 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
7583 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
7584 if (runningApps != null && runningApps.size() > 0) {
7585 Set<String> extList = new HashSet<String>();
7586 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
7587 if (app.pkgList != null) {
7588 for (String pkg : app.pkgList) {
7589 extList.add(pkg);
7590 }
7591 }
7592 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007593 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007594 for (String pkg : extList) {
7595 try {
7596 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
7597 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
7598 retList.add(info);
7599 }
7600 } catch (RemoteException e) {
7601 }
7602 }
7603 }
7604 return retList;
7605 }
7606
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007607 @Override
7608 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007609 if (checkCallingPermission(android.Manifest.permission.DUMP)
7610 != PackageManager.PERMISSION_GRANTED) {
7611 pw.println("Permission Denial: can't dump ActivityManager from from pid="
7612 + Binder.getCallingPid()
7613 + ", uid=" + Binder.getCallingUid()
7614 + " without permission "
7615 + android.Manifest.permission.DUMP);
7616 return;
7617 }
7618
7619 boolean dumpAll = false;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007620 boolean dumpClient = false;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007621
7622 int opti = 0;
7623 while (opti < args.length) {
7624 String opt = args[opti];
7625 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
7626 break;
7627 }
7628 opti++;
7629 if ("-a".equals(opt)) {
7630 dumpAll = true;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007631 } else if ("-c".equals(opt)) {
7632 dumpClient = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007633 } else if ("-h".equals(opt)) {
7634 pw.println("Activity manager dump options:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007635 pw.println(" [-a] [-c] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007636 pw.println(" cmd may be one of:");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007637 pw.println(" a[ctivities]: activity stack state");
7638 pw.println(" b[roadcasts]: broadcast state");
7639 pw.println(" i[ntents]: pending intent state");
7640 pw.println(" p[rocesses]: process state");
7641 pw.println(" o[om]: out of memory management");
7642 pw.println(" prov[iders]: content provider state");
7643 pw.println(" s[ervices]: service state");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007644 pw.println(" service [COMP_SPEC]: service client-side state");
7645 pw.println(" cmd may also be a COMP_SPEC to dump activities.");
7646 pw.println(" COMP_SPEC may also be a component name (com.foo/.myApp),");
7647 pw.println(" a partial substring in a component name, an");
7648 pw.println(" ActivityRecord hex object identifier, or");
Dianne Hackbornf9302322011-06-14 18:36:14 -07007649 pw.println(" \"all\" for all objects, or");
7650 pw.println(" \"top\" for the top activity.");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007651 pw.println(" -a: include all available server state.");
7652 pw.println(" -c: include client state.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007653 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007654 } else {
7655 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007656 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007657 }
7658
7659 // Is the caller requesting to dump a particular piece of data?
7660 if (opti < args.length) {
7661 String cmd = args[opti];
7662 opti++;
7663 if ("activities".equals(cmd) || "a".equals(cmd)) {
7664 synchronized (this) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007665 dumpActivitiesLocked(fd, pw, args, opti, true, dumpClient);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007666 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007667 return;
7668 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
7669 synchronized (this) {
7670 dumpBroadcastsLocked(fd, pw, args, opti, true);
7671 }
7672 return;
7673 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
7674 synchronized (this) {
7675 dumpPendingIntentsLocked(fd, pw, args, opti, true);
7676 }
7677 return;
7678 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
7679 synchronized (this) {
7680 dumpProcessesLocked(fd, pw, args, opti, true);
7681 }
7682 return;
Dianne Hackborn287952c2010-09-22 22:34:31 -07007683 } else if ("oom".equals(cmd) || "o".equals(cmd)) {
7684 synchronized (this) {
7685 dumpOomLocked(fd, pw, args, opti, true);
7686 }
7687 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007688 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
7689 synchronized (this) {
7690 dumpProvidersLocked(fd, pw, args, opti, true);
7691 }
7692 return;
7693 } else if ("service".equals(cmd)) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007694 String[] newArgs;
7695 String name;
7696 if (opti >= args.length) {
7697 name = null;
7698 newArgs = EMPTY_STRING_ARRAY;
7699 } else {
7700 name = args[opti];
7701 opti++;
7702 newArgs = new String[args.length - opti];
7703 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
7704 }
7705 if (!dumpService(fd, pw, name, newArgs, 0, dumpAll)) {
7706 pw.println("No services match: " + name);
7707 pw.println("Use -h for help.");
7708 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007709 return;
7710 } else if ("services".equals(cmd) || "s".equals(cmd)) {
7711 synchronized (this) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007712 dumpServicesLocked(fd, pw, args, opti, true, dumpClient);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007713 }
7714 return;
Dianne Hackborn625ac272010-09-17 18:29:22 -07007715 } else {
7716 // Dumping a single activity?
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007717 if (!dumpActivity(fd, pw, cmd, args, opti, dumpAll)) {
7718 pw.println("Bad activity command, or no activities match: " + cmd);
7719 pw.println("Use -h for help.");
Dianne Hackborn625ac272010-09-17 18:29:22 -07007720 }
Dianne Hackborn30d71892010-12-11 10:37:55 -08007721 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007722 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007723 }
7724
7725 // No piece of data specified, dump everything.
7726 synchronized (this) {
7727 boolean needSep;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007728 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007729 if (needSep) {
7730 pw.println(" ");
7731 }
7732 if (dumpAll) {
7733 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007734 }
7735 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
7736 if (needSep) {
7737 pw.println(" ");
7738 }
7739 if (dumpAll) {
7740 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007741 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007742 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007743 if (needSep) {
7744 pw.println(" ");
7745 }
7746 if (dumpAll) {
7747 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007748 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007749 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll, dumpClient);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007750 if (needSep) {
7751 pw.println(" ");
7752 }
7753 if (dumpAll) {
7754 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007755 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007756 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, dumpClient);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007757 if (needSep) {
7758 pw.println(" ");
7759 }
7760 if (dumpAll) {
7761 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007762 }
7763 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
7764 }
7765 }
7766
7767 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007768 int opti, boolean dumpAll, boolean dumpClient) {
7769 pw.println("ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)");
7770 pw.println(" Main stack:");
7771 dumpHistoryList(fd, pw, mMainStack.mHistory, " ", "Hist", true, !dumpAll, dumpClient);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007772 pw.println(" ");
7773 pw.println(" Running activities (most recent first):");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007774 dumpHistoryList(fd, pw, mMainStack.mLRUActivities, " ", "Run", false, !dumpAll, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007775 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007776 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007777 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007778 dumpHistoryList(fd, pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false,
7779 !dumpAll, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007780 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007781 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007782 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007783 pw.println(" Activities waiting to stop:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007784 dumpHistoryList(fd, pw, mMainStack.mStoppingActivities, " ", "Stop", false,
7785 !dumpAll, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007786 }
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08007787 if (mMainStack.mGoingToSleepActivities.size() > 0) {
7788 pw.println(" ");
7789 pw.println(" Activities waiting to sleep:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007790 dumpHistoryList(fd, pw, mMainStack.mGoingToSleepActivities, " ", "Sleep", false,
7791 !dumpAll, false);
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08007792 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007793 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007794 pw.println(" ");
7795 pw.println(" Activities waiting to finish:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007796 dumpHistoryList(fd, pw, mMainStack.mFinishingActivities, " ", "Fin", false,
7797 !dumpAll, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007798 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007799
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007800 pw.println(" ");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007801 if (mMainStack.mPausingActivity != null) {
7802 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
7803 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007804 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007805 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007806 if (dumpAll) {
7807 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
7808 pw.println(" mSleepTimeout: " + mMainStack.mSleepTimeout);
7809 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007810
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007811 if (mRecentTasks.size() > 0) {
7812 pw.println();
7813 pw.println(" Recent tasks:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007814
7815 final int N = mRecentTasks.size();
7816 for (int i=0; i<N; i++) {
7817 TaskRecord tr = mRecentTasks.get(i);
7818 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
7819 pw.println(tr);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007820 if (dumpAll) {
7821 mRecentTasks.get(i).dump(pw, " ");
7822 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007823 }
7824 }
7825
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007826 if (dumpAll) {
7827 pw.println(" ");
7828 pw.println(" mCurTask: " + mCurTask);
7829 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007830
7831 return true;
7832 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07007833
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007834 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7835 int opti, boolean dumpAll) {
7836 boolean needSep = false;
7837 int numPers = 0;
7838
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007839 pw.println("ACTIVITY MANAGER RUNNING PROCESSES (dumpsys activity processes)");
7840
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007841 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007842 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
7843 final int NA = procs.size();
7844 for (int ia=0; ia<NA; ia++) {
7845 if (!needSep) {
7846 pw.println(" All known processes:");
7847 needSep = true;
7848 }
7849 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007850 pw.print(r.persistent ? " *PERS*" : " *APP*");
7851 pw.print(" UID "); pw.print(procs.keyAt(ia));
7852 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007853 r.dump(pw, " ");
7854 if (r.persistent) {
7855 numPers++;
7856 }
7857 }
7858 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007859 }
7860
7861 if (mLruProcesses.size() > 0) {
7862 if (needSep) pw.println(" ");
7863 needSep = true;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007864 pw.println(" Process LRU list (most recent first):");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007865 dumpProcessOomList(pw, this, mLruProcesses, " ",
7866 "Proc", "PERS", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007867 needSep = true;
7868 }
7869
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007870 if (dumpAll) {
7871 synchronized (mPidsSelfLocked) {
7872 if (mPidsSelfLocked.size() > 0) {
7873 if (needSep) pw.println(" ");
7874 needSep = true;
7875 pw.println(" PID mappings:");
7876 for (int i=0; i<mPidsSelfLocked.size(); i++) {
7877 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
7878 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
7879 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007880 }
7881 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007882 }
7883
7884 if (mForegroundProcesses.size() > 0) {
7885 if (needSep) pw.println(" ");
7886 needSep = true;
7887 pw.println(" Foreground Processes:");
7888 for (int i=0; i<mForegroundProcesses.size(); i++) {
7889 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
7890 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007891 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007892 }
7893
7894 if (mPersistentStartingProcesses.size() > 0) {
7895 if (needSep) pw.println(" ");
7896 needSep = true;
7897 pw.println(" Persisent processes that are starting:");
7898 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007899 "Starting Norm", "Restarting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007900 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007901
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007902 if (mRemovedProcesses.size() > 0) {
7903 if (needSep) pw.println(" ");
7904 needSep = true;
7905 pw.println(" Processes that are being removed:");
7906 dumpProcessList(pw, this, mRemovedProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007907 "Removed Norm", "Removed PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007908 }
7909
7910 if (mProcessesOnHold.size() > 0) {
7911 if (needSep) pw.println(" ");
7912 needSep = true;
7913 pw.println(" Processes that are on old until the system is ready:");
7914 dumpProcessList(pw, this, mProcessesOnHold, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007915 "OnHold Norm", "OnHold PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007916 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007917
Dianne Hackborn287952c2010-09-22 22:34:31 -07007918 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007919
7920 if (mProcessCrashTimes.getMap().size() > 0) {
7921 if (needSep) pw.println(" ");
7922 needSep = true;
7923 pw.println(" Time since processes crashed:");
7924 long now = SystemClock.uptimeMillis();
7925 for (Map.Entry<String, SparseArray<Long>> procs
7926 : mProcessCrashTimes.getMap().entrySet()) {
7927 SparseArray<Long> uids = procs.getValue();
7928 final int N = uids.size();
7929 for (int i=0; i<N; i++) {
7930 pw.print(" Process "); pw.print(procs.getKey());
7931 pw.print(" uid "); pw.print(uids.keyAt(i));
7932 pw.print(": last crashed ");
7933 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007934 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007935 }
7936 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007937 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007938
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007939 if (mBadProcesses.getMap().size() > 0) {
7940 if (needSep) pw.println(" ");
7941 needSep = true;
7942 pw.println(" Bad processes:");
7943 for (Map.Entry<String, SparseArray<Long>> procs
7944 : mBadProcesses.getMap().entrySet()) {
7945 SparseArray<Long> uids = procs.getValue();
7946 final int N = uids.size();
7947 for (int i=0; i<N; i++) {
7948 pw.print(" Bad process "); pw.print(procs.getKey());
7949 pw.print(" uid "); pw.print(uids.keyAt(i));
7950 pw.print(": crashed at time ");
7951 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007952 }
7953 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007954 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007955
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007956 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007957 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007958 if (mHeavyWeightProcess != null) {
7959 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7960 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007961 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007962 if (dumpAll) {
7963 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackborn3d0724d2011-05-12 15:39:41 -07007964 if (mCompatModePackages.getPackages().size() > 0) {
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07007965 pw.println(" mScreenCompatPackages:");
7966 for (Map.Entry<String, Integer> entry
7967 : mCompatModePackages.getPackages().entrySet()) {
7968 String pkg = entry.getKey();
7969 int mode = entry.getValue();
7970 pw.print(" "); pw.print(pkg); pw.print(": ");
7971 pw.print(mode); pw.println();
7972 }
Dianne Hackbornaa9d84c2011-05-09 19:00:59 -07007973 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007974 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007975 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
7976 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
7977 || mOrigWaitForDebugger) {
7978 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
7979 + " mDebugTransient=" + mDebugTransient
7980 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
7981 }
7982 if (mAlwaysFinishActivities || mController != null) {
7983 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
7984 + " mController=" + mController);
7985 }
7986 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007987 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007988 pw.println(" mStartRunning=" + mStartRunning
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07007989 + " mProcessesReady=" + mProcessesReady
7990 + " mSystemReady=" + mSystemReady);
7991 pw.println(" mBooting=" + mBooting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007992 + " mBooted=" + mBooted
7993 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn287952c2010-09-22 22:34:31 -07007994 pw.print(" mLastPowerCheckRealtime=");
7995 TimeUtils.formatDuration(mLastPowerCheckRealtime, pw);
7996 pw.println("");
7997 pw.print(" mLastPowerCheckUptime=");
7998 TimeUtils.formatDuration(mLastPowerCheckUptime, pw);
7999 pw.println("");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008000 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
8001 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07008002 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008003 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008004
8005 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008006 }
8007
Dianne Hackborn287952c2010-09-22 22:34:31 -07008008 boolean dumpProcessesToGc(FileDescriptor fd, PrintWriter pw, String[] args,
8009 int opti, boolean needSep, boolean dumpAll) {
8010 if (mProcessesToGc.size() > 0) {
8011 if (needSep) pw.println(" ");
8012 needSep = true;
8013 pw.println(" Processes that are waiting to GC:");
8014 long now = SystemClock.uptimeMillis();
8015 for (int i=0; i<mProcessesToGc.size(); i++) {
8016 ProcessRecord proc = mProcessesToGc.get(i);
8017 pw.print(" Process "); pw.println(proc);
8018 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
8019 pw.print(", last gced=");
8020 pw.print(now-proc.lastRequestedGc);
8021 pw.print(" ms ago, last lowMem=");
8022 pw.print(now-proc.lastLowMemory);
8023 pw.println(" ms ago");
8024
8025 }
8026 }
8027 return needSep;
8028 }
8029
8030 boolean dumpOomLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8031 int opti, boolean dumpAll) {
8032 boolean needSep = false;
8033
8034 if (mLruProcesses.size() > 0) {
8035 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>(mLruProcesses);
8036
8037 Comparator<ProcessRecord> comparator = new Comparator<ProcessRecord>() {
8038 @Override
8039 public int compare(ProcessRecord object1, ProcessRecord object2) {
8040 if (object1.setAdj != object2.setAdj) {
8041 return object1.setAdj > object2.setAdj ? -1 : 1;
8042 }
8043 if (object1.setSchedGroup != object2.setSchedGroup) {
8044 return object1.setSchedGroup > object2.setSchedGroup ? -1 : 1;
8045 }
8046 if (object1.keeping != object2.keeping) {
8047 return object1.keeping ? -1 : 1;
8048 }
8049 if (object1.pid != object2.pid) {
8050 return object1.pid > object2.pid ? -1 : 1;
8051 }
8052 return 0;
8053 }
8054 };
8055
8056 Collections.sort(procs, comparator);
8057
8058 if (needSep) pw.println(" ");
8059 needSep = true;
8060 pw.println(" Process OOM control:");
8061 dumpProcessOomList(pw, this, procs, " ",
8062 "Proc", "PERS", true);
8063 needSep = true;
8064 }
8065
8066 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
8067
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008068 pw.println();
Dianne Hackborn287952c2010-09-22 22:34:31 -07008069 pw.println(" mHomeProcess: " + mHomeProcess);
8070 if (mHeavyWeightProcess != null) {
8071 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
8072 }
8073
8074 return true;
8075 }
8076
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008077 /**
8078 * There are three ways to call this:
8079 * - no service specified: dump all the services
8080 * - a flattened component name that matched an existing service was specified as the
8081 * first arg: dump that one service
8082 * - the first arg isn't the flattened component name of an existing service:
8083 * dump all services whose component contains the first arg as a substring
8084 */
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008085 protected boolean dumpService(FileDescriptor fd, PrintWriter pw, String name, String[] args,
8086 int opti, boolean dumpAll) {
8087 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008088
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008089 if ("all".equals(name)) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07008090 synchronized (this) {
8091 for (ServiceRecord r1 : mServices.values()) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008092 services.add(r1);
8093 }
8094 }
8095 } else {
8096 ComponentName componentName = name != null
8097 ? ComponentName.unflattenFromString(name) : null;
8098 int objectId = 0;
8099 if (componentName == null) {
8100 // Not a '/' separated full component name; maybe an object ID?
8101 try {
8102 objectId = Integer.parseInt(name, 16);
8103 name = null;
8104 componentName = null;
8105 } catch (RuntimeException e) {
8106 }
8107 }
8108
8109 synchronized (this) {
8110 for (ServiceRecord r1 : mServices.values()) {
8111 if (componentName != null) {
8112 if (r1.name.equals(componentName)) {
8113 services.add(r1);
8114 }
8115 } else if (name != null) {
8116 if (r1.name.flattenToString().contains(name)) {
8117 services.add(r1);
8118 }
8119 } else if (System.identityHashCode(r1) == objectId) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07008120 services.add(r1);
8121 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008122 }
8123 }
8124 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008125
8126 if (services.size() <= 0) {
8127 return false;
8128 }
8129
8130 boolean needSep = false;
8131 for (int i=0; i<services.size(); i++) {
8132 if (needSep) {
8133 pw.println();
8134 }
8135 needSep = true;
8136 dumpService("", fd, pw, services.get(i), args, dumpAll);
8137 }
8138 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008139 }
8140
8141 /**
8142 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
8143 * there is a thread associated with the service.
8144 */
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008145 private void dumpService(String prefix, FileDescriptor fd, PrintWriter pw,
8146 final ServiceRecord r, String[] args, boolean dumpAll) {
8147 String innerPrefix = prefix + " ";
8148 synchronized (this) {
8149 pw.print(prefix); pw.print("SERVICE ");
8150 pw.print(r.shortName); pw.print(" ");
8151 pw.print(Integer.toHexString(System.identityHashCode(r)));
8152 pw.print(" pid=");
8153 if (r.app != null) pw.println(r.app.pid);
8154 else pw.println("(not running)");
8155 if (dumpAll) {
8156 r.dump(pw, innerPrefix);
8157 }
8158 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008159 if (r.app != null && r.app.thread != null) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008160 pw.print(prefix); pw.println(" Client:");
8161 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008162 try {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008163 TransferPipe tp = new TransferPipe();
8164 try {
8165 r.app.thread.dumpService(tp.getWriteFd().getFileDescriptor(), r, args);
8166 tp.setBufferPrefix(prefix + " ");
8167 tp.go(fd);
8168 } finally {
8169 tp.kill();
8170 }
8171 } catch (IOException e) {
8172 pw.println(prefix + " Failure while dumping the service: " + e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008173 } catch (RemoteException e) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008174 pw.println(prefix + " Got a RemoteException while dumping the service");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008175 }
8176 }
8177 }
8178
Dianne Hackborn625ac272010-09-17 18:29:22 -07008179 /**
8180 * There are three things that cmd can be:
8181 * - a flattened component name that matched an existing activity
8182 * - the cmd arg isn't the flattened component name of an existing activity:
8183 * dump all activity whose component contains the cmd as a substring
8184 * - A hex number of the ActivityRecord object instance.
8185 */
8186 protected boolean dumpActivity(FileDescriptor fd, PrintWriter pw, String name, String[] args,
8187 int opti, boolean dumpAll) {
Dianne Hackborn625ac272010-09-17 18:29:22 -07008188 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008189
8190 if ("all".equals(name)) {
8191 synchronized (this) {
8192 for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
Dianne Hackborn625ac272010-09-17 18:29:22 -07008193 activities.add(r1);
8194 }
8195 }
Dianne Hackbornf9302322011-06-14 18:36:14 -07008196 } else if ("top".equals(name)) {
8197 synchronized (this) {
8198 final int N = mMainStack.mHistory.size();
8199 if (N > 0) {
8200 activities.add((ActivityRecord)mMainStack.mHistory.get(N-1));
8201 }
8202 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008203 } else {
8204 ComponentName componentName = ComponentName.unflattenFromString(name);
8205 int objectId = 0;
8206 if (componentName == null) {
8207 // Not a '/' separated full component name; maybe an object ID?
8208 try {
8209 objectId = Integer.parseInt(name, 16);
8210 name = null;
8211 componentName = null;
8212 } catch (RuntimeException e) {
8213 }
8214 }
8215
8216 synchronized (this) {
8217 for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
8218 if (componentName != null) {
8219 if (r1.intent.getComponent().equals(componentName)) {
8220 activities.add(r1);
8221 }
8222 } else if (name != null) {
8223 if (r1.intent.getComponent().flattenToString().contains(name)) {
8224 activities.add(r1);
8225 }
8226 } else if (System.identityHashCode(r1) == objectId) {
8227 activities.add(r1);
8228 }
8229 }
8230 }
Dianne Hackborn625ac272010-09-17 18:29:22 -07008231 }
8232
8233 if (activities.size() <= 0) {
8234 return false;
8235 }
8236
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008237 String[] newArgs = new String[args.length - opti];
8238 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
8239
Dianne Hackborn30d71892010-12-11 10:37:55 -08008240 TaskRecord lastTask = null;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008241 boolean needSep = false;
Dianne Hackborn30d71892010-12-11 10:37:55 -08008242 for (int i=activities.size()-1; i>=0; i--) {
8243 ActivityRecord r = (ActivityRecord)activities.get(i);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008244 if (needSep) {
8245 pw.println();
8246 }
8247 needSep = true;
8248 synchronized (this) {
8249 if (lastTask != r.task) {
8250 lastTask = r.task;
8251 pw.print("TASK "); pw.print(lastTask.affinity);
8252 pw.print(" id="); pw.println(lastTask.taskId);
8253 if (dumpAll) {
8254 lastTask.dump(pw, " ");
8255 }
Dianne Hackborn30d71892010-12-11 10:37:55 -08008256 }
8257 }
8258 dumpActivity(" ", fd, pw, activities.get(i), newArgs, dumpAll);
Dianne Hackborn625ac272010-09-17 18:29:22 -07008259 }
8260 return true;
8261 }
8262
8263 /**
8264 * Invokes IApplicationThread.dumpActivity() on the thread of the specified activity if
8265 * there is a thread associated with the activity.
8266 */
Dianne Hackborn30d71892010-12-11 10:37:55 -08008267 private void dumpActivity(String prefix, FileDescriptor fd, PrintWriter pw,
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008268 final ActivityRecord r, String[] args, boolean dumpAll) {
8269 String innerPrefix = prefix + " ";
Dianne Hackborn30d71892010-12-11 10:37:55 -08008270 synchronized (this) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008271 pw.print(prefix); pw.print("ACTIVITY "); pw.print(r.shortComponentName);
8272 pw.print(" "); pw.print(Integer.toHexString(System.identityHashCode(r)));
8273 pw.print(" pid=");
Dianne Hackborn30d71892010-12-11 10:37:55 -08008274 if (r.app != null) pw.println(r.app.pid);
8275 else pw.println("(not running)");
8276 if (dumpAll) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008277 r.dump(pw, innerPrefix);
Dianne Hackborn625ac272010-09-17 18:29:22 -07008278 }
Dianne Hackborn625ac272010-09-17 18:29:22 -07008279 }
8280 if (r.app != null && r.app.thread != null) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008281 // flush anything that is already in the PrintWriter since the thread is going
8282 // to write to the file descriptor directly
8283 pw.flush();
Dianne Hackborn625ac272010-09-17 18:29:22 -07008284 try {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008285 TransferPipe tp = new TransferPipe();
8286 try {
8287 r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(), r,
8288 innerPrefix, args);
8289 tp.go(fd);
8290 } finally {
8291 tp.kill();
8292 }
8293 } catch (IOException e) {
8294 pw.println(innerPrefix + "Failure while dumping the activity: " + e);
Dianne Hackborn625ac272010-09-17 18:29:22 -07008295 } catch (RemoteException e) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008296 pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
Dianne Hackborn625ac272010-09-17 18:29:22 -07008297 }
8298 }
8299 }
8300
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008301 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8302 int opti, boolean dumpAll) {
8303 boolean needSep = false;
8304
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008305 pw.println("ACTIVITY MANAGER BROADCAST STATE (dumpsys activity broadcasts)");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008306 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008307 if (mRegisteredReceivers.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008308 pw.println(" Registered Receivers:");
8309 Iterator it = mRegisteredReceivers.values().iterator();
8310 while (it.hasNext()) {
8311 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008312 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008313 r.dump(pw, " ");
8314 }
8315 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008316
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008317 pw.println();
8318 pw.println(" Receiver Resolver Table:");
8319 mReceiverResolver.dump(pw, null, " ", null, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008320 needSep = true;
8321 }
8322
8323 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
8324 || mPendingBroadcast != null) {
8325 if (mParallelBroadcasts.size() > 0) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008326 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008327 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008328 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008329 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
8330 pw.println(" Broadcast #" + i + ":");
8331 mParallelBroadcasts.get(i).dump(pw, " ");
8332 }
8333 if (mOrderedBroadcasts.size() > 0) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008334 pw.println();
Dianne Hackborn399cccb2010-04-13 22:57:49 -07008335 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008336 }
8337 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
8338 pw.println(" Serialized Broadcast #" + i + ":");
8339 mOrderedBroadcasts.get(i).dump(pw, " ");
8340 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008341 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008342 pw.println(" Pending broadcast:");
8343 if (mPendingBroadcast != null) {
8344 mPendingBroadcast.dump(pw, " ");
8345 } else {
8346 pw.println(" (null)");
8347 }
8348 needSep = true;
8349 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008350
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008351 if (needSep) {
8352 pw.println();
8353 }
8354 pw.println(" Historical broadcasts:");
8355 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
8356 BroadcastRecord r = mBroadcastHistory[i];
8357 if (r == null) {
8358 break;
8359 }
8360 if (dumpAll) {
8361 pw.print(" Historical Broadcast #"); pw.print(i); pw.println(":");
8362 r.dump(pw, " ");
8363 } else {
8364 if (i >= 50) {
8365 pw.println(" ...");
Dianne Hackborn12527f92009-11-11 17:39:50 -08008366 break;
8367 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008368 pw.print(" #"); pw.print(i); pw.print(": "); pw.println(r);
Dianne Hackborn12527f92009-11-11 17:39:50 -08008369 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008370 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008371 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008372
8373 if (mStickyBroadcasts != null) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008374 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008375 pw.println(" Sticky broadcasts:");
8376 StringBuilder sb = new StringBuilder(128);
8377 for (Map.Entry<String, ArrayList<Intent>> ent
8378 : mStickyBroadcasts.entrySet()) {
8379 pw.print(" * Sticky action "); pw.print(ent.getKey());
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008380 if (dumpAll) {
8381 pw.println(":");
8382 ArrayList<Intent> intents = ent.getValue();
8383 final int N = intents.size();
8384 for (int i=0; i<N; i++) {
8385 sb.setLength(0);
8386 sb.append(" Intent: ");
8387 intents.get(i).toShortString(sb, true, false);
8388 pw.println(sb.toString());
8389 Bundle bundle = intents.get(i).getExtras();
8390 if (bundle != null) {
8391 pw.print(" ");
8392 pw.println(bundle.toString());
8393 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008394 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008395 } else {
8396 pw.println("");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008397 }
8398 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008399 needSep = true;
8400 }
8401
8402 if (dumpAll) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008403 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008404 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008405 pw.println(" mHandler:");
8406 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008407 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008408 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008409
8410 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008411 }
8412
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008413 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008414 int opti, boolean dumpAll, boolean dumpClient) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008415 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008416
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008417 pw.println("ACTIVITY MANAGER SERVICES (dumpsys activity services)");
8418 if (mServices.size() > 0) {
8419 pw.println(" Active services:");
8420 long nowReal = SystemClock.elapsedRealtime();
8421 Iterator<ServiceRecord> it = mServices.values().iterator();
8422 needSep = false;
8423 while (it.hasNext()) {
8424 ServiceRecord r = it.next();
8425 if (needSep) {
8426 pw.println();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008427 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008428 pw.print(" * "); pw.println(r);
8429 if (dumpAll) {
8430 r.dump(pw, " ");
8431 needSep = true;
8432 } else {
8433 pw.print(" app="); pw.println(r.app);
8434 pw.print(" created=");
8435 TimeUtils.formatDuration(r.createTime, nowReal, pw);
8436 pw.print(" started="); pw.print(r.startRequested);
8437 pw.print(" connections="); pw.println(r.connections.size());
8438 }
8439 if (dumpClient && r.app != null && r.app.thread != null) {
8440 pw.println(" Client:");
8441 pw.flush();
8442 try {
8443 TransferPipe tp = new TransferPipe();
8444 try {
8445 r.app.thread.dumpService(
8446 tp.getWriteFd().getFileDescriptor(), r, args);
8447 tp.setBufferPrefix(" ");
8448 // Short timeout, since blocking here can
8449 // deadlock with the application.
8450 tp.go(fd, 2000);
8451 } finally {
8452 tp.kill();
8453 }
8454 } catch (IOException e) {
8455 pw.println(" Failure while dumping the service: " + e);
8456 } catch (RemoteException e) {
8457 pw.println(" Got a RemoteException while dumping the service");
8458 }
8459 needSep = true;
8460 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008461 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008462 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008463 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008464
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008465 if (mPendingServices.size() > 0) {
8466 if (needSep) pw.println(" ");
8467 pw.println(" Pending services:");
8468 for (int i=0; i<mPendingServices.size(); i++) {
8469 ServiceRecord r = mPendingServices.get(i);
8470 pw.print(" * Pending "); pw.println(r);
8471 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008472 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008473 needSep = true;
8474 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008475
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008476 if (mRestartingServices.size() > 0) {
8477 if (needSep) pw.println(" ");
8478 pw.println(" Restarting services:");
8479 for (int i=0; i<mRestartingServices.size(); i++) {
8480 ServiceRecord r = mRestartingServices.get(i);
8481 pw.print(" * Restarting "); pw.println(r);
8482 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008483 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008484 needSep = true;
8485 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008486
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008487 if (mStoppingServices.size() > 0) {
8488 if (needSep) pw.println(" ");
8489 pw.println(" Stopping services:");
8490 for (int i=0; i<mStoppingServices.size(); i++) {
8491 ServiceRecord r = mStoppingServices.get(i);
8492 pw.print(" * Stopping "); pw.println(r);
8493 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008494 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008495 needSep = true;
8496 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008497
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008498 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008499 if (mServiceConnections.size() > 0) {
8500 if (needSep) pw.println(" ");
8501 pw.println(" Connection bindings to services:");
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008502 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008503 = mServiceConnections.values().iterator();
8504 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008505 ArrayList<ConnectionRecord> r = it.next();
8506 for (int i=0; i<r.size(); i++) {
8507 pw.print(" * "); pw.println(r.get(i));
8508 r.get(i).dump(pw, " ");
8509 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008510 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008511 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008512 }
8513 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008514
8515 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008516 }
8517
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008518 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8519 int opti, boolean dumpAll) {
8520 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008521
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008522 pw.println("ACTIVITY MANAGER CONTENT PROVIDERS (dumpsys activity providers)");
8523 if (mProvidersByClass.size() > 0) {
8524 if (needSep) pw.println(" ");
8525 pw.println(" Published content providers (by class):");
8526 Iterator<Map.Entry<String, ContentProviderRecord>> it
8527 = mProvidersByClass.entrySet().iterator();
8528 while (it.hasNext()) {
8529 Map.Entry<String, ContentProviderRecord> e = it.next();
8530 ContentProviderRecord r = e.getValue();
8531 if (dumpAll) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008532 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008533 r.dump(pw, " ");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008534 } else {
8535 pw.print(" * "); pw.print(r.name.toShortString());
8536 if (r.app != null) {
8537 pw.println(":");
8538 pw.print(" "); pw.println(r.app);
8539 } else {
8540 pw.println();
8541 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008542 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008543 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008544 needSep = true;
8545 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008546
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008547 if (dumpAll) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008548 if (mProvidersByName.size() > 0) {
8549 pw.println(" ");
8550 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -07008551 Iterator<Map.Entry<String, ContentProviderRecord>> it
8552 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008553 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008554 Map.Entry<String, ContentProviderRecord> e = it.next();
8555 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008556 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
8557 pw.println(r);
8558 }
8559 needSep = true;
8560 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008561 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008562
8563 if (mLaunchingProviders.size() > 0) {
8564 if (needSep) pw.println(" ");
8565 pw.println(" Launching content providers:");
8566 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
8567 pw.print(" Launching #"); pw.print(i); pw.print(": ");
8568 pw.println(mLaunchingProviders.get(i));
8569 }
8570 needSep = true;
8571 }
8572
8573 if (mGrantedUriPermissions.size() > 0) {
8574 pw.println();
8575 pw.println("Granted Uri Permissions:");
8576 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
8577 int uid = mGrantedUriPermissions.keyAt(i);
8578 HashMap<Uri, UriPermission> perms
8579 = mGrantedUriPermissions.valueAt(i);
8580 pw.print(" * UID "); pw.print(uid);
8581 pw.println(" holds:");
8582 for (UriPermission perm : perms.values()) {
8583 pw.print(" "); pw.println(perm);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008584 if (dumpAll) {
8585 perm.dump(pw, " ");
8586 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008587 }
8588 }
8589 needSep = true;
8590 }
8591
8592 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008593 }
8594
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008595 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8596 int opti, boolean dumpAll) {
8597 boolean needSep = false;
8598
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008599 if (this.mIntentSenderRecords.size() > 0) {
8600 pw.println("ACTIVITY MANAGER PENDING INTENTS (dumpsys activity intents)");
8601 Iterator<WeakReference<PendingIntentRecord>> it
8602 = mIntentSenderRecords.values().iterator();
8603 while (it.hasNext()) {
8604 WeakReference<PendingIntentRecord> ref = it.next();
8605 PendingIntentRecord rec = ref != null ? ref.get(): null;
8606 needSep = true;
8607 if (rec != null) {
8608 pw.print(" * "); pw.println(rec);
8609 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008610 rec.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008611 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008612 } else {
8613 pw.print(" * "); pw.println(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008614 }
8615 }
8616 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008617
8618 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008619 }
8620
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008621 private static final void dumpHistoryList(FileDescriptor fd, PrintWriter pw, List list,
8622 String prefix, String label, boolean complete, boolean brief, boolean client) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008623 TaskRecord lastTask = null;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008624 boolean needNL = false;
8625 final String innerPrefix = prefix + " ";
8626 final String[] args = new String[0];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008627 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008628 final ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackbornf26fd992011-04-08 18:14:09 -07008629 final boolean full = !brief && (complete || !r.isInHistory());
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008630 if (needNL) {
8631 pw.println(" ");
8632 needNL = false;
8633 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008634 if (lastTask != r.task) {
8635 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008636 pw.print(prefix);
8637 pw.print(full ? "* " : " ");
8638 pw.println(lastTask);
8639 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008640 lastTask.dump(pw, prefix + " ");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008641 } else if (complete) {
8642 // Complete + brief == give a summary. Isn't that obvious?!?
8643 if (lastTask.intent != null) {
8644 pw.print(prefix); pw.print(" "); pw.println(lastTask.intent);
8645 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008646 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008647 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008648 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
8649 pw.print(" #"); pw.print(i); pw.print(": ");
8650 pw.println(r);
8651 if (full) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008652 r.dump(pw, innerPrefix);
8653 } else if (complete) {
8654 // Complete + brief == give a summary. Isn't that obvious?!?
8655 pw.print(innerPrefix); pw.println(r.intent);
8656 if (r.app != null) {
8657 pw.print(innerPrefix); pw.println(r.app);
8658 }
8659 }
8660 if (client && r.app != null && r.app.thread != null) {
8661 // flush anything that is already in the PrintWriter since the thread is going
8662 // to write to the file descriptor directly
8663 pw.flush();
8664 try {
8665 TransferPipe tp = new TransferPipe();
8666 try {
8667 r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(), r,
8668 innerPrefix, args);
8669 // Short timeout, since blocking here can
8670 // deadlock with the application.
8671 tp.go(fd, 2000);
8672 } finally {
8673 tp.kill();
8674 }
8675 } catch (IOException e) {
8676 pw.println(innerPrefix + "Failure while dumping the activity: " + e);
8677 } catch (RemoteException e) {
8678 pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
8679 }
8680 needNL = true;
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008681 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008682 }
8683 }
8684
Dianne Hackborn09c916b2009-12-08 14:50:51 -08008685 private static String buildOomTag(String prefix, String space, int val, int base) {
8686 if (val == base) {
8687 if (space == null) return prefix;
8688 return prefix + " ";
8689 }
8690 return prefix + "+" + Integer.toString(val-base);
8691 }
8692
8693 private static final int dumpProcessList(PrintWriter pw,
8694 ActivityManagerService service, List list,
Dianne Hackborn287952c2010-09-22 22:34:31 -07008695 String prefix, String normalLabel, String persistentLabel) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008696 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07008697 final int N = list.size()-1;
8698 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008699 ProcessRecord r = (ProcessRecord)list.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008700 pw.println(String.format("%s%s #%2d: %s",
8701 prefix, (r.persistent ? persistentLabel : normalLabel),
8702 i, r.toString()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008703 if (r.persistent) {
8704 numPers++;
8705 }
8706 }
8707 return numPers;
8708 }
8709
Dianne Hackborn287952c2010-09-22 22:34:31 -07008710 private static final void dumpProcessOomList(PrintWriter pw,
8711 ActivityManagerService service, List<ProcessRecord> list,
8712 String prefix, String normalLabel, String persistentLabel,
8713 boolean inclDetails) {
8714
8715 final long curRealtime = SystemClock.elapsedRealtime();
8716 final long realtimeSince = curRealtime - service.mLastPowerCheckRealtime;
8717 final long curUptime = SystemClock.uptimeMillis();
8718 final long uptimeSince = curUptime - service.mLastPowerCheckUptime;
8719
8720 final int N = list.size()-1;
8721 for (int i=N; i>=0; i--) {
8722 ProcessRecord r = list.get(i);
8723 String oomAdj;
8724 if (r.setAdj >= EMPTY_APP_ADJ) {
8725 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
8726 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
8727 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
8728 } else if (r.setAdj >= HOME_APP_ADJ) {
8729 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
8730 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
8731 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
8732 } else if (r.setAdj >= BACKUP_APP_ADJ) {
8733 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
8734 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
8735 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
8736 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
8737 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
8738 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
8739 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
8740 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
8741 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
8742 } else if (r.setAdj >= CORE_SERVER_ADJ) {
8743 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
8744 } else if (r.setAdj >= SYSTEM_ADJ) {
8745 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
8746 } else {
8747 oomAdj = Integer.toString(r.setAdj);
8748 }
8749 String schedGroup;
8750 switch (r.setSchedGroup) {
8751 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
8752 schedGroup = "B";
8753 break;
8754 case Process.THREAD_GROUP_DEFAULT:
8755 schedGroup = "F";
8756 break;
8757 default:
8758 schedGroup = Integer.toString(r.setSchedGroup);
8759 break;
8760 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07008761 String foreground;
8762 if (r.foregroundActivities) {
8763 foreground = "A";
8764 } else if (r.foregroundServices) {
8765 foreground = "S";
8766 } else {
8767 foreground = " ";
8768 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -07008769 pw.println(String.format("%s%s #%2d: adj=%s/%s%s trm=%2d %s (%s)",
Dianne Hackborn287952c2010-09-22 22:34:31 -07008770 prefix, (r.persistent ? persistentLabel : normalLabel),
Dianne Hackbornce86ba82011-07-13 19:33:41 -07008771 N-i, oomAdj, schedGroup, foreground, r.trimMemoryLevel,
8772 r.toShortString(), r.adjType));
Dianne Hackborn287952c2010-09-22 22:34:31 -07008773 if (r.adjSource != null || r.adjTarget != null) {
8774 pw.print(prefix);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008775 pw.print(" ");
Dianne Hackborn287952c2010-09-22 22:34:31 -07008776 if (r.adjTarget instanceof ComponentName) {
8777 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
8778 } else if (r.adjTarget != null) {
8779 pw.print(r.adjTarget.toString());
8780 } else {
8781 pw.print("{null}");
8782 }
8783 pw.print("<=");
8784 if (r.adjSource instanceof ProcessRecord) {
8785 pw.print("Proc{");
8786 pw.print(((ProcessRecord)r.adjSource).toShortString());
8787 pw.println("}");
8788 } else if (r.adjSource != null) {
8789 pw.println(r.adjSource.toString());
8790 } else {
8791 pw.println("{null}");
8792 }
8793 }
8794 if (inclDetails) {
8795 pw.print(prefix);
8796 pw.print(" ");
8797 pw.print("oom: max="); pw.print(r.maxAdj);
8798 pw.print(" hidden="); pw.print(r.hiddenAdj);
8799 pw.print(" curRaw="); pw.print(r.curRawAdj);
8800 pw.print(" setRaw="); pw.print(r.setRawAdj);
8801 pw.print(" cur="); pw.print(r.curAdj);
8802 pw.print(" set="); pw.println(r.setAdj);
8803 pw.print(prefix);
8804 pw.print(" ");
8805 pw.print("keeping="); pw.print(r.keeping);
8806 pw.print(" hidden="); pw.print(r.hidden);
8807 pw.print(" empty="); pw.println(r.empty);
8808
8809 if (!r.keeping) {
8810 if (r.lastWakeTime != 0) {
8811 long wtime;
8812 BatteryStatsImpl stats = service.mBatteryStatsService.getActiveStatistics();
8813 synchronized (stats) {
8814 wtime = stats.getProcessWakeTime(r.info.uid,
8815 r.pid, curRealtime);
8816 }
8817 long timeUsed = wtime - r.lastWakeTime;
8818 pw.print(prefix);
8819 pw.print(" ");
8820 pw.print("keep awake over ");
8821 TimeUtils.formatDuration(realtimeSince, pw);
8822 pw.print(" used ");
8823 TimeUtils.formatDuration(timeUsed, pw);
8824 pw.print(" (");
8825 pw.print((timeUsed*100)/realtimeSince);
8826 pw.println("%)");
8827 }
8828 if (r.lastCpuTime != 0) {
8829 long timeUsed = r.curCpuTime - r.lastCpuTime;
8830 pw.print(prefix);
8831 pw.print(" ");
8832 pw.print("run cpu over ");
8833 TimeUtils.formatDuration(uptimeSince, pw);
8834 pw.print(" used ");
8835 TimeUtils.formatDuration(timeUsed, pw);
8836 pw.print(" (");
8837 pw.print((timeUsed*100)/uptimeSince);
8838 pw.println("%)");
8839 }
8840 }
8841 }
8842 }
8843 }
8844
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008845 ArrayList<ProcessRecord> collectProcesses(PrintWriter pw, String[] args) {
8846 ArrayList<ProcessRecord> procs;
8847 synchronized (this) {
8848 if (args != null && args.length > 0
8849 && args[0].charAt(0) != '-') {
8850 procs = new ArrayList<ProcessRecord>();
8851 int pid = -1;
8852 try {
8853 pid = Integer.parseInt(args[0]);
8854 } catch (NumberFormatException e) {
8855
8856 }
8857 for (int i=mLruProcesses.size()-1; i>=0; i--) {
8858 ProcessRecord proc = mLruProcesses.get(i);
8859 if (proc.pid == pid) {
8860 procs.add(proc);
8861 } else if (proc.processName.equals(args[0])) {
8862 procs.add(proc);
8863 }
8864 }
8865 if (procs.size() <= 0) {
8866 pw.println("No process found for: " + args[0]);
8867 return null;
8868 }
8869 } else {
8870 procs = new ArrayList<ProcessRecord>(mLruProcesses);
8871 }
8872 }
8873 return procs;
8874 }
8875
8876 final void dumpGraphicsHardwareUsage(FileDescriptor fd,
8877 PrintWriter pw, String[] args) {
8878 ArrayList<ProcessRecord> procs = collectProcesses(pw, args);
8879 if (procs == null) {
8880 return;
8881 }
8882
8883 long uptime = SystemClock.uptimeMillis();
8884 long realtime = SystemClock.elapsedRealtime();
8885 pw.println("Applications Graphics Acceleration Info:");
8886 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
8887
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008888 for (int i = procs.size() - 1 ; i >= 0 ; i--) {
8889 ProcessRecord r = procs.get(i);
Chet Haase9c1e23b2011-03-24 10:51:31 -07008890 if (r.thread != null) {
8891 pw.println("\n** Graphics info for pid " + r.pid + " [" + r.processName + "] **");
8892 pw.flush();
8893 try {
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07008894 TransferPipe tp = new TransferPipe();
8895 try {
8896 r.thread.dumpGfxInfo(tp.getWriteFd().getFileDescriptor(), args);
8897 tp.go(fd);
8898 } finally {
8899 tp.kill();
8900 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008901 } catch (IOException e) {
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07008902 pw.println("Failure while dumping the app: " + r);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008903 pw.flush();
Chet Haase9c1e23b2011-03-24 10:51:31 -07008904 } catch (RemoteException e) {
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07008905 pw.println("Got a RemoteException while dumping the app " + r);
Chet Haase9c1e23b2011-03-24 10:51:31 -07008906 pw.flush();
8907 }
8908 }
8909 }
Chet Haase9c1e23b2011-03-24 10:51:31 -07008910 }
8911
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07008912 final static class MemItem {
8913 final String label;
8914 final long pss;
8915
8916 public MemItem(String _label, long _pss) {
8917 label = _label;
8918 pss = _pss;
8919 }
8920 }
8921
8922 final void dumpMemItems(PrintWriter pw, String prefix, ArrayList<MemItem> items) {
8923 Collections.sort(items, new Comparator<MemItem>() {
8924 @Override
8925 public int compare(MemItem lhs, MemItem rhs) {
8926 if (lhs.pss < rhs.pss) {
8927 return 1;
8928 } else if (lhs.pss > rhs.pss) {
8929 return -1;
8930 }
8931 return 0;
8932 }
8933 });
8934
8935 for (int i=0; i<items.size(); i++) {
8936 MemItem mi = items.get(i);
8937 pw.print(prefix); pw.printf("%8d Kb: ", mi.pss); pw.println(mi.label);
8938 }
8939 }
8940
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008941 final void dumpApplicationMemoryUsage(FileDescriptor fd,
8942 PrintWriter pw, String prefix, String[] args) {
8943 ArrayList<ProcessRecord> procs = collectProcesses(pw, args);
8944 if (procs == null) {
8945 return;
8946 }
8947
Dianne Hackborn6447ca32009-04-07 19:50:08 -07008948 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008949 long uptime = SystemClock.uptimeMillis();
8950 long realtime = SystemClock.elapsedRealtime();
8951
8952 if (isCheckinRequest) {
8953 // short checkin version
8954 pw.println(uptime + "," + realtime);
8955 pw.flush();
8956 } else {
8957 pw.println("Applications Memory Usage (kB):");
8958 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
8959 }
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07008960
8961 ArrayList<MemItem> procMems = new ArrayList<MemItem>();
8962 long nativePss=0, dalvikPss=0, otherPss=0;
8963 long[] miscPss = new long[Debug.MemoryInfo.NUM_OTHER_STATS];
8964
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008965 for (int i = procs.size() - 1 ; i >= 0 ; i--) {
8966 ProcessRecord r = procs.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008967 if (r.thread != null) {
8968 if (!isCheckinRequest) {
8969 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
8970 pw.flush();
8971 }
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07008972 Debug.MemoryInfo mi = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008973 try {
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07008974 mi = r.thread.dumpMemInfo(fd, args);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008975 } catch (RemoteException e) {
8976 if (!isCheckinRequest) {
8977 pw.println("Got RemoteException!");
8978 pw.flush();
8979 }
8980 }
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07008981 if (!isCheckinRequest && mi != null) {
8982 procMems.add(new MemItem(r.processName + " (pid " + r.pid + ")",
8983 mi.getTotalPss()));
8984
8985 nativePss += mi.nativePss;
8986 dalvikPss += mi.dalvikPss;
8987 otherPss += mi.otherPss;
8988 for (int j=0; j<Debug.MemoryInfo.NUM_OTHER_STATS; j++) {
8989 long mem = mi.getOtherPss(j);
8990 miscPss[j] += mem;
8991 otherPss -= mem;
8992 }
8993 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008994 }
8995 }
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07008996
8997 if (!isCheckinRequest && procs.size() > 1) {
8998 ArrayList<MemItem> catMems = new ArrayList<MemItem>();
8999
9000 catMems.add(new MemItem("Native", nativePss));
9001 catMems.add(new MemItem("Dalvik", dalvikPss));
9002 catMems.add(new MemItem("Unknown", otherPss));
9003 for (int j=0; j<Debug.MemoryInfo.NUM_OTHER_STATS; j++) {
9004 catMems.add(new MemItem(Debug.MemoryInfo.getOtherLabel(j), miscPss[j]));
9005 }
9006
9007 pw.println();
9008 pw.println("Total PSS by process:");
9009 dumpMemItems(pw, " ", procMems);
9010 pw.println();
9011 pw.println("Total PSS by category:");
9012 dumpMemItems(pw, " ", catMems);
9013 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009014 }
9015
9016 /**
9017 * Searches array of arguments for the specified string
9018 * @param args array of argument strings
9019 * @param value value to search for
9020 * @return true if the value is contained in the array
9021 */
9022 private static boolean scanArgs(String[] args, String value) {
9023 if (args != null) {
9024 for (String arg : args) {
9025 if (value.equals(arg)) {
9026 return true;
9027 }
9028 }
9029 }
9030 return false;
9031 }
9032
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009033 private final void killServicesLocked(ProcessRecord app,
9034 boolean allowRestart) {
9035 // Report disconnected services.
9036 if (false) {
9037 // XXX we are letting the client link to the service for
9038 // death notifications.
9039 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009040 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009041 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009042 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009043 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009044 Iterator<ArrayList<ConnectionRecord>> jt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009045 = r.connections.values().iterator();
9046 while (jt.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009047 ArrayList<ConnectionRecord> cl = jt.next();
9048 for (int i=0; i<cl.size(); i++) {
9049 ConnectionRecord c = cl.get(i);
9050 if (c.binding.client != app) {
9051 try {
9052 //c.conn.connected(r.className, null);
9053 } catch (Exception e) {
9054 // todo: this should be asynchronous!
9055 Slog.w(TAG, "Exception thrown disconnected servce "
9056 + r.shortName
9057 + " from app " + app.processName, e);
9058 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009059 }
9060 }
9061 }
9062 }
9063 }
9064 }
9065 }
9066
9067 // Clean up any connections this application has to other services.
9068 if (app.connections.size() > 0) {
9069 Iterator<ConnectionRecord> it = app.connections.iterator();
9070 while (it.hasNext()) {
9071 ConnectionRecord r = it.next();
9072 removeConnectionLocked(r, app, null);
9073 }
9074 }
9075 app.connections.clear();
9076
9077 if (app.services.size() != 0) {
9078 // Any services running in the application need to be placed
9079 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07009080 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009081 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009082 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009083 synchronized (sr.stats.getBatteryStats()) {
9084 sr.stats.stopLaunchedLocked();
9085 }
9086 sr.app = null;
9087 sr.executeNesting = 0;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009088 if (mStoppingServices.remove(sr)) {
9089 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
9090 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009091
9092 boolean hasClients = sr.bindings.size() > 0;
9093 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009094 Iterator<IntentBindRecord> bindings
9095 = sr.bindings.values().iterator();
9096 while (bindings.hasNext()) {
9097 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009098 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009099 + ": shouldUnbind=" + b.hasBound);
9100 b.binder = null;
9101 b.requested = b.received = b.hasBound = false;
9102 }
9103 }
9104
Dianne Hackborn070783f2010-12-29 16:46:28 -08009105 if (sr.crashCount >= 2 && (sr.serviceInfo.applicationInfo.flags
9106 &ApplicationInfo.FLAG_PERSISTENT) == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009107 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009108 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009109 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009110 sr.crashCount, sr.shortName, app.pid);
9111 bringDownServiceLocked(sr, true);
9112 } else if (!allowRestart) {
9113 bringDownServiceLocked(sr, true);
9114 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009115 boolean canceled = scheduleServiceRestartLocked(sr, true);
9116
9117 // Should the service remain running? Note that in the
9118 // extreme case of so many attempts to deliver a command
9119 // that it failed, that we also will stop it here.
9120 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
9121 if (sr.pendingStarts.size() == 0) {
9122 sr.startRequested = false;
9123 if (!hasClients) {
9124 // Whoops, no reason to restart!
9125 bringDownServiceLocked(sr, true);
9126 }
9127 }
9128 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009129 }
9130 }
9131
9132 if (!allowRestart) {
9133 app.services.clear();
9134 }
9135 }
9136
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009137 // Make sure we have no more records on the stopping list.
9138 int i = mStoppingServices.size();
9139 while (i > 0) {
9140 i--;
9141 ServiceRecord sr = mStoppingServices.get(i);
9142 if (sr.app == app) {
9143 mStoppingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009144 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009145 }
9146 }
9147
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009148 app.executingServices.clear();
9149 }
9150
9151 private final void removeDyingProviderLocked(ProcessRecord proc,
9152 ContentProviderRecord cpr) {
9153 synchronized (cpr) {
9154 cpr.launchingApp = null;
9155 cpr.notifyAll();
9156 }
9157
9158 mProvidersByClass.remove(cpr.info.name);
9159 String names[] = cpr.info.authority.split(";");
9160 for (int j = 0; j < names.length; j++) {
9161 mProvidersByName.remove(names[j]);
9162 }
9163
9164 Iterator<ProcessRecord> cit = cpr.clients.iterator();
9165 while (cit.hasNext()) {
9166 ProcessRecord capp = cit.next();
9167 if (!capp.persistent && capp.thread != null
9168 && capp.pid != 0
9169 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07009170 Slog.i(TAG, "Kill " + capp.processName
9171 + " (pid " + capp.pid + "): provider " + cpr.info.name
9172 + " in dying process " + proc.processName);
9173 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
9174 capp.processName, capp.setAdj, "dying provider " + proc.processName);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07009175 Process.killProcessQuiet(capp.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009176 }
9177 }
9178
9179 mLaunchingProviders.remove(cpr);
9180 }
9181
9182 /**
9183 * Main code for cleaning up a process when it has gone away. This is
9184 * called both as a result of the process dying, or directly when stopping
9185 * a process when running in single process mode.
9186 */
9187 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
9188 boolean restarting, int index) {
9189 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009190 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009191 }
9192
Dianne Hackborn36124872009-10-08 16:22:03 -07009193 mProcessesToGc.remove(app);
9194
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009195 // Dismiss any open dialogs.
9196 if (app.crashDialog != null) {
9197 app.crashDialog.dismiss();
9198 app.crashDialog = null;
9199 }
9200 if (app.anrDialog != null) {
9201 app.anrDialog.dismiss();
9202 app.anrDialog = null;
9203 }
9204 if (app.waitDialog != null) {
9205 app.waitDialog.dismiss();
9206 app.waitDialog = null;
9207 }
9208
9209 app.crashing = false;
9210 app.notResponding = false;
9211
9212 app.resetPackageList();
9213 app.thread = null;
9214 app.forcingToForeground = null;
9215 app.foregroundServices = false;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07009216 app.foregroundActivities = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009217
9218 killServicesLocked(app, true);
9219
9220 boolean restart = false;
9221
9222 int NL = mLaunchingProviders.size();
9223
9224 // Remove published content providers.
9225 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009226 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009227 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009228 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009229 cpr.provider = null;
9230 cpr.app = null;
9231
9232 // See if someone is waiting for this provider... in which
9233 // case we don't remove it, but just let it restart.
9234 int i = 0;
9235 if (!app.bad) {
9236 for (; i<NL; i++) {
9237 if (mLaunchingProviders.get(i) == cpr) {
9238 restart = true;
9239 break;
9240 }
9241 }
9242 } else {
9243 i = NL;
9244 }
9245
9246 if (i >= NL) {
9247 removeDyingProviderLocked(app, cpr);
9248 NL = mLaunchingProviders.size();
9249 }
9250 }
9251 app.pubProviders.clear();
9252 }
9253
Dianne Hackbornf670ef72009-11-16 13:59:16 -08009254 // Take care of any launching providers waiting for this process.
9255 if (checkAppInLaunchingProvidersLocked(app, false)) {
9256 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009257 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08009258
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009259 // Unregister from connected content providers.
9260 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07009261 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009262 while (it.hasNext()) {
9263 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
9264 cpr.clients.remove(app);
9265 }
9266 app.conProviders.clear();
9267 }
9268
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009269 // At this point there may be remaining entries in mLaunchingProviders
9270 // where we were the only one waiting, so they are no longer of use.
9271 // Look for these and clean up if found.
9272 // XXX Commented out for now. Trying to figure out a way to reproduce
9273 // the actual situation to identify what is actually going on.
9274 if (false) {
9275 for (int i=0; i<NL; i++) {
9276 ContentProviderRecord cpr = (ContentProviderRecord)
9277 mLaunchingProviders.get(i);
9278 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
9279 synchronized (cpr) {
9280 cpr.launchingApp = null;
9281 cpr.notifyAll();
9282 }
9283 }
9284 }
9285 }
9286
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009287 skipCurrentReceiverLocked(app);
9288
9289 // Unregister any receivers.
9290 if (app.receivers.size() > 0) {
9291 Iterator<ReceiverList> it = app.receivers.iterator();
9292 while (it.hasNext()) {
9293 removeReceiverLocked(it.next());
9294 }
9295 app.receivers.clear();
9296 }
9297
Christopher Tate181fafa2009-05-14 11:12:14 -07009298 // If the app is undergoing backup, tell the backup manager about it
9299 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009300 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -07009301 try {
9302 IBackupManager bm = IBackupManager.Stub.asInterface(
9303 ServiceManager.getService(Context.BACKUP_SERVICE));
9304 bm.agentDisconnected(app.info.packageName);
9305 } catch (RemoteException e) {
9306 // can't happen; backup manager is local
9307 }
9308 }
9309
Jeff Sharkey287bd832011-05-28 19:36:26 -07009310 mHandler.obtainMessage(DISPATCH_PROCESS_DIED, app.pid, app.info.uid, null).sendToTarget();
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07009311
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009312 // If the caller is restarting this app, then leave it in its
9313 // current lists and let the caller take care of it.
9314 if (restarting) {
9315 return;
9316 }
9317
9318 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009319 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009320 "Removing non-persistent process during cleanup: " + app);
9321 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07009322 if (mHeavyWeightProcess == app) {
9323 mHeavyWeightProcess = null;
9324 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
9325 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009326 } else if (!app.removed) {
9327 // This app is persistent, so we need to keep its record around.
9328 // If it is not already on the pending app list, add it there
9329 // and start a new process for it.
9330 app.thread = null;
9331 app.forcingToForeground = null;
9332 app.foregroundServices = false;
9333 if (mPersistentStartingProcesses.indexOf(app) < 0) {
9334 mPersistentStartingProcesses.add(app);
9335 restart = true;
9336 }
9337 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07009338 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
9339 "Clean-up removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009340 mProcessesOnHold.remove(app);
9341
The Android Open Source Project4df24232009-03-05 14:34:35 -08009342 if (app == mHomeProcess) {
9343 mHomeProcess = null;
9344 }
9345
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009346 if (restart) {
9347 // We have components that still need to be running in the
9348 // process, so re-launch it.
9349 mProcessNames.put(app.processName, app.info.uid, app);
9350 startProcessLocked(app, "restart", app.processName);
9351 } else if (app.pid > 0 && app.pid != MY_PID) {
9352 // Goodbye!
9353 synchronized (mPidsSelfLocked) {
9354 mPidsSelfLocked.remove(app.pid);
9355 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
9356 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009357 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009358 }
9359 }
9360
Dianne Hackbornf670ef72009-11-16 13:59:16 -08009361 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
9362 // Look through the content providers we are waiting to have launched,
9363 // and if any run in this process then either schedule a restart of
9364 // the process or kill the client waiting for it if this process has
9365 // gone bad.
9366 int NL = mLaunchingProviders.size();
9367 boolean restart = false;
9368 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009369 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08009370 if (cpr.launchingApp == app) {
9371 if (!alwaysBad && !app.bad) {
9372 restart = true;
9373 } else {
9374 removeDyingProviderLocked(app, cpr);
9375 NL = mLaunchingProviders.size();
9376 }
9377 }
9378 }
9379 return restart;
9380 }
9381
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009382 // =========================================================
9383 // SERVICES
9384 // =========================================================
9385
9386 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
9387 ActivityManager.RunningServiceInfo info =
9388 new ActivityManager.RunningServiceInfo();
9389 info.service = r.name;
9390 if (r.app != null) {
9391 info.pid = r.app.pid;
9392 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -07009393 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009394 info.process = r.processName;
9395 info.foreground = r.isForeground;
9396 info.activeSince = r.createTime;
9397 info.started = r.startRequested;
9398 info.clientCount = r.connections.size();
9399 info.crashCount = r.crashCount;
9400 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07009401 if (r.isForeground) {
9402 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
9403 }
9404 if (r.startRequested) {
9405 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
9406 }
Dan Egnor42471dd2010-01-07 17:25:22 -08009407 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -07009408 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
9409 }
9410 if (r.app != null && r.app.persistent) {
9411 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
9412 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009413
9414 for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
9415 for (int i=0; i<connl.size(); i++) {
9416 ConnectionRecord conn = connl.get(i);
9417 if (conn.clientLabel != 0) {
9418 info.clientPackage = conn.binding.client.info.packageName;
9419 info.clientLabel = conn.clientLabel;
9420 return info;
9421 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009422 }
9423 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009424 return info;
9425 }
9426
9427 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
9428 int flags) {
9429 synchronized (this) {
9430 ArrayList<ActivityManager.RunningServiceInfo> res
9431 = new ArrayList<ActivityManager.RunningServiceInfo>();
9432
9433 if (mServices.size() > 0) {
9434 Iterator<ServiceRecord> it = mServices.values().iterator();
9435 while (it.hasNext() && res.size() < maxNum) {
9436 res.add(makeRunningServiceInfoLocked(it.next()));
9437 }
9438 }
9439
9440 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
9441 ServiceRecord r = mRestartingServices.get(i);
9442 ActivityManager.RunningServiceInfo info =
9443 makeRunningServiceInfoLocked(r);
9444 info.restarting = r.nextRestartTime;
9445 res.add(info);
9446 }
9447
9448 return res;
9449 }
9450 }
9451
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009452 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
9453 synchronized (this) {
9454 ServiceRecord r = mServices.get(name);
9455 if (r != null) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009456 for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
9457 for (int i=0; i<conn.size(); i++) {
9458 if (conn.get(i).clientIntent != null) {
9459 return conn.get(i).clientIntent;
9460 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009461 }
9462 }
9463 }
9464 }
9465 return null;
9466 }
9467
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009468 private final ServiceRecord findServiceLocked(ComponentName name,
9469 IBinder token) {
9470 ServiceRecord r = mServices.get(name);
9471 return r == token ? r : null;
9472 }
9473
9474 private final class ServiceLookupResult {
9475 final ServiceRecord record;
9476 final String permission;
9477
9478 ServiceLookupResult(ServiceRecord _record, String _permission) {
9479 record = _record;
9480 permission = _permission;
9481 }
9482 };
9483
9484 private ServiceLookupResult findServiceLocked(Intent service,
9485 String resolvedType) {
9486 ServiceRecord r = null;
9487 if (service.getComponent() != null) {
9488 r = mServices.get(service.getComponent());
9489 }
9490 if (r == null) {
9491 Intent.FilterComparison filter = new Intent.FilterComparison(service);
9492 r = mServicesByIntent.get(filter);
9493 }
9494
9495 if (r == null) {
9496 try {
9497 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009498 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009499 service, resolvedType, 0);
9500 ServiceInfo sInfo =
9501 rInfo != null ? rInfo.serviceInfo : null;
9502 if (sInfo == null) {
9503 return null;
9504 }
9505
9506 ComponentName name = new ComponentName(
9507 sInfo.applicationInfo.packageName, sInfo.name);
9508 r = mServices.get(name);
9509 } catch (RemoteException ex) {
9510 // pm is in same process, this will never happen.
9511 }
9512 }
9513 if (r != null) {
9514 int callingPid = Binder.getCallingPid();
9515 int callingUid = Binder.getCallingUid();
9516 if (checkComponentPermission(r.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009517 callingPid, callingUid, r.appInfo.uid, r.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009518 != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009519 if (!r.exported) {
9520 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
9521 + " from pid=" + callingPid
9522 + ", uid=" + callingUid
9523 + " that is not exported from uid " + r.appInfo.uid);
9524 return new ServiceLookupResult(null, "not exported from uid "
9525 + r.appInfo.uid);
9526 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009527 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009528 + " from pid=" + callingPid
9529 + ", uid=" + callingUid
9530 + " requires " + r.permission);
9531 return new ServiceLookupResult(null, r.permission);
9532 }
9533 return new ServiceLookupResult(r, null);
9534 }
9535 return null;
9536 }
9537
9538 private class ServiceRestarter implements Runnable {
9539 private ServiceRecord mService;
9540
9541 void setService(ServiceRecord service) {
9542 mService = service;
9543 }
9544
9545 public void run() {
9546 synchronized(ActivityManagerService.this) {
9547 performServiceRestartLocked(mService);
9548 }
9549 }
9550 }
9551
9552 private ServiceLookupResult retrieveServiceLocked(Intent service,
9553 String resolvedType, int callingPid, int callingUid) {
9554 ServiceRecord r = null;
9555 if (service.getComponent() != null) {
9556 r = mServices.get(service.getComponent());
9557 }
9558 Intent.FilterComparison filter = new Intent.FilterComparison(service);
9559 r = mServicesByIntent.get(filter);
9560 if (r == null) {
9561 try {
9562 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009563 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -07009564 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009565 ServiceInfo sInfo =
9566 rInfo != null ? rInfo.serviceInfo : null;
9567 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009568 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009569 ": not found");
9570 return null;
9571 }
9572
9573 ComponentName name = new ComponentName(
9574 sInfo.applicationInfo.packageName, sInfo.name);
9575 r = mServices.get(name);
9576 if (r == null) {
9577 filter = new Intent.FilterComparison(service.cloneFilter());
9578 ServiceRestarter res = new ServiceRestarter();
9579 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
9580 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
9581 synchronized (stats) {
9582 ss = stats.getServiceStatsLocked(
9583 sInfo.applicationInfo.uid, sInfo.packageName,
9584 sInfo.name);
9585 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -08009586 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009587 res.setService(r);
9588 mServices.put(name, r);
9589 mServicesByIntent.put(filter, r);
9590
9591 // Make sure this component isn't in the pending list.
9592 int N = mPendingServices.size();
9593 for (int i=0; i<N; i++) {
9594 ServiceRecord pr = mPendingServices.get(i);
9595 if (pr.name.equals(name)) {
9596 mPendingServices.remove(i);
9597 i--;
9598 N--;
9599 }
9600 }
9601 }
9602 } catch (RemoteException ex) {
9603 // pm is in same process, this will never happen.
9604 }
9605 }
9606 if (r != null) {
9607 if (checkComponentPermission(r.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009608 callingPid, callingUid, r.appInfo.uid, r.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009609 != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009610 if (!r.exported) {
9611 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
9612 + " from pid=" + callingPid
9613 + ", uid=" + callingUid
9614 + " that is not exported from uid " + r.appInfo.uid);
9615 return new ServiceLookupResult(null, "not exported from uid "
9616 + r.appInfo.uid);
9617 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009618 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009619 + " from pid=" + callingPid
9620 + ", uid=" + callingUid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009621 + " requires " + r.permission);
9622 return new ServiceLookupResult(null, r.permission);
9623 }
9624 return new ServiceLookupResult(r, null);
9625 }
9626 return null;
9627 }
9628
Dianne Hackborn287952c2010-09-22 22:34:31 -07009629 private final void bumpServiceExecutingLocked(ServiceRecord r, String why) {
9630 if (DEBUG_SERVICE) Log.v(TAG, ">>> EXECUTING "
9631 + why + " of " + r + " in app " + r.app);
9632 else if (DEBUG_SERVICE_EXECUTING) Log.v(TAG, ">>> EXECUTING "
9633 + why + " of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009634 long now = SystemClock.uptimeMillis();
9635 if (r.executeNesting == 0 && r.app != null) {
9636 if (r.app.executingServices.size() == 0) {
9637 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
9638 msg.obj = r.app;
9639 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
9640 }
9641 r.app.executingServices.add(r);
9642 }
9643 r.executeNesting++;
9644 r.executingStart = now;
9645 }
9646
9647 private final void sendServiceArgsLocked(ServiceRecord r,
9648 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009649 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009650 if (N == 0) {
9651 return;
9652 }
9653
Dianne Hackborn39792d22010-08-19 18:01:52 -07009654 while (r.pendingStarts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009655 try {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009656 ServiceRecord.StartItem si = r.pendingStarts.remove(0);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009657 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
9658 + r + " " + r.intent + " args=" + si.intent);
Dianne Hackborn3a28f222011-03-01 12:25:54 -08009659 if (si.intent == null && N > 1) {
9660 // If somehow we got a dummy null intent in the middle,
9661 // then skip it. DO NOT skip a null intent when it is
9662 // the only one in the list -- this is to support the
9663 // onStartCommand(null) case.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009664 continue;
9665 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009666 si.deliveredTime = SystemClock.uptimeMillis();
9667 r.deliveredStarts.add(si);
9668 si.deliveryCount++;
Dianne Hackborn3a28f222011-03-01 12:25:54 -08009669 if (si.targetPermissionUid >= 0 && si.intent != null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009670 grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
Dianne Hackborn7e269642010-08-25 19:50:20 -07009671 r.packageName, si.intent, si.getUriPermissionsLocked());
Dianne Hackborn39792d22010-08-19 18:01:52 -07009672 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07009673 bumpServiceExecutingLocked(r, "start");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009674 if (!oomAdjusted) {
9675 oomAdjusted = true;
9676 updateOomAdjLocked(r.app);
9677 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009678 int flags = 0;
9679 if (si.deliveryCount > 0) {
9680 flags |= Service.START_FLAG_RETRY;
9681 }
9682 if (si.doneExecutingCount > 0) {
9683 flags |= Service.START_FLAG_REDELIVERY;
9684 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07009685 r.app.thread.scheduleServiceArgs(r, si.taskRemoved, si.id, flags, si.intent);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009686 } catch (RemoteException e) {
9687 // Remote process gone... we'll let the normal cleanup take
9688 // care of this.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009689 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009690 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009691 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009692 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009693 break;
9694 }
9695 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009696 }
9697
9698 private final boolean requestServiceBindingLocked(ServiceRecord r,
9699 IntentBindRecord i, boolean rebind) {
9700 if (r.app == null || r.app.thread == null) {
9701 // If service is not currently running, can't yet bind.
9702 return false;
9703 }
9704 if ((!i.requested || rebind) && i.apps.size() > 0) {
9705 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009706 bumpServiceExecutingLocked(r, "bind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009707 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
9708 if (!rebind) {
9709 i.requested = true;
9710 }
9711 i.hasBound = true;
9712 i.doRebind = false;
9713 } catch (RemoteException e) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009714 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009715 return false;
9716 }
9717 }
9718 return true;
9719 }
9720
9721 private final void requestServiceBindingsLocked(ServiceRecord r) {
9722 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
9723 while (bindings.hasNext()) {
9724 IntentBindRecord i = bindings.next();
9725 if (!requestServiceBindingLocked(r, i, false)) {
9726 break;
9727 }
9728 }
9729 }
9730
9731 private final void realStartServiceLocked(ServiceRecord r,
9732 ProcessRecord app) throws RemoteException {
9733 if (app.thread == null) {
9734 throw new RemoteException();
9735 }
9736
9737 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -07009738 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009739
9740 app.services.add(r);
Dianne Hackborn287952c2010-09-22 22:34:31 -07009741 bumpServiceExecutingLocked(r, "create");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009742 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009743
9744 boolean created = false;
9745 try {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07009746 mStringBuilder.setLength(0);
9747 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009748 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009749 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -07009750 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009751 synchronized (r.stats.getBatteryStats()) {
9752 r.stats.startLaunchedLocked();
9753 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07009754 ensurePackageDexOpt(r.serviceInfo.packageName);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04009755 app.thread.scheduleCreateService(r, r.serviceInfo,
9756 compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo));
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009757 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009758 created = true;
9759 } finally {
9760 if (!created) {
9761 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009762 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009763 }
9764 }
9765
9766 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009767
9768 // If the service is in the started state, and there are no
9769 // pending arguments, then fake up one so its onStartCommand() will
9770 // be called.
9771 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07009772 r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
9773 null, -1));
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009774 }
9775
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009776 sendServiceArgsLocked(r, true);
9777 }
9778
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009779 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
9780 boolean allowCancel) {
9781 boolean canceled = false;
9782
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009783 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009784 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -07009785 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009786
Dianne Hackborn070783f2010-12-29 16:46:28 -08009787 if ((r.serviceInfo.applicationInfo.flags
9788 &ApplicationInfo.FLAG_PERSISTENT) != 0) {
9789 minDuration /= 4;
9790 }
9791
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009792 // Any delivered but not yet finished starts should be put back
9793 // on the pending list.
9794 final int N = r.deliveredStarts.size();
9795 if (N > 0) {
9796 for (int i=N-1; i>=0; i--) {
9797 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
Dianne Hackborn39792d22010-08-19 18:01:52 -07009798 si.removeUriPermissionsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009799 if (si.intent == null) {
9800 // We'll generate this again if needed.
9801 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
9802 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
9803 r.pendingStarts.add(0, si);
9804 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
9805 dur *= 2;
9806 if (minDuration < dur) minDuration = dur;
9807 if (resetTime < dur) resetTime = dur;
9808 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009809 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009810 + r.name);
9811 canceled = true;
9812 }
9813 }
9814 r.deliveredStarts.clear();
9815 }
9816
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009817 r.totalRestartCount++;
9818 if (r.restartDelay == 0) {
9819 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009820 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009821 } else {
9822 // If it has been a "reasonably long time" since the service
9823 // was started, then reset our restart duration back to
9824 // the beginning, so we don't infinitely increase the duration
9825 // on a service that just occasionally gets killed (which is
9826 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009827 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009828 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009829 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009830 } else {
Dianne Hackborn070783f2010-12-29 16:46:28 -08009831 if ((r.serviceInfo.applicationInfo.flags
9832 &ApplicationInfo.FLAG_PERSISTENT) != 0) {
9833 // Services in peristent processes will restart much more
9834 // quickly, since they are pretty important. (Think SystemUI).
9835 r.restartDelay += minDuration/2;
9836 } else {
9837 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
9838 if (r.restartDelay < minDuration) {
9839 r.restartDelay = minDuration;
9840 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009841 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009842 }
9843 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009844
9845 r.nextRestartTime = now + r.restartDelay;
9846
9847 // Make sure that we don't end up restarting a bunch of services
9848 // all at the same time.
9849 boolean repeat;
9850 do {
9851 repeat = false;
9852 for (int i=mRestartingServices.size()-1; i>=0; i--) {
9853 ServiceRecord r2 = mRestartingServices.get(i);
9854 if (r2 != r && r.nextRestartTime
9855 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
9856 && r.nextRestartTime
9857 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
9858 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
9859 r.restartDelay = r.nextRestartTime - now;
9860 repeat = true;
9861 break;
9862 }
9863 }
9864 } while (repeat);
9865
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009866 if (!mRestartingServices.contains(r)) {
9867 mRestartingServices.add(r);
9868 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009869
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009870 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009871
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009872 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009873 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009874 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009875 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009876 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -08009877 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009878 r.shortName, r.restartDelay);
9879
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009880 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009881 }
9882
9883 final void performServiceRestartLocked(ServiceRecord r) {
9884 if (!mRestartingServices.contains(r)) {
9885 return;
9886 }
9887 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
9888 }
9889
9890 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
9891 if (r.restartDelay == 0) {
9892 return false;
9893 }
9894 r.resetRestartCounter();
9895 mRestartingServices.remove(r);
9896 mHandler.removeCallbacks(r.restarter);
9897 return true;
9898 }
9899
9900 private final boolean bringUpServiceLocked(ServiceRecord r,
9901 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009902 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009903 //r.dump(" ");
9904
Dianne Hackborn36124872009-10-08 16:22:03 -07009905 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009906 sendServiceArgsLocked(r, false);
9907 return true;
9908 }
9909
9910 if (!whileRestarting && r.restartDelay > 0) {
9911 // If waiting for a restart, then do nothing.
9912 return true;
9913 }
9914
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009915 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009916
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009917 // We are now bringing the service up, so no longer in the
9918 // restarting state.
9919 mRestartingServices.remove(r);
9920
Dianne Hackborne7f97212011-02-24 14:40:20 -08009921 // Service is now being launched, its package can't be stopped.
9922 try {
9923 AppGlobals.getPackageManager().setPackageStoppedState(
9924 r.packageName, false);
9925 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08009926 } catch (IllegalArgumentException e) {
9927 Slog.w(TAG, "Failed trying to unstop package "
9928 + r.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08009929 }
9930
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009931 final String appName = r.processName;
9932 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
9933 if (app != null && app.thread != null) {
9934 try {
Dianne Hackborn6c418d52011-06-29 14:05:33 -07009935 app.addPackage(r.appInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009936 realStartServiceLocked(r, app);
9937 return true;
9938 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009939 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009940 }
9941
9942 // If a dead object exception was thrown -- fall through to
9943 // restart the application.
9944 }
9945
Dianne Hackborn36124872009-10-08 16:22:03 -07009946 // Not running -- get it started, and enqueue this service record
9947 // to be executed when the app comes up.
9948 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
9949 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009950 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -07009951 + r.appInfo.packageName + "/"
9952 + r.appInfo.uid + " for service "
9953 + r.intent.getIntent() + ": process is bad");
9954 bringDownServiceLocked(r, true);
9955 return false;
9956 }
9957
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009958 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009959 mPendingServices.add(r);
9960 }
Dianne Hackborn36124872009-10-08 16:22:03 -07009961
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009962 return true;
9963 }
9964
9965 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009966 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009967 //r.dump(" ");
9968
9969 // Does it still need to run?
9970 if (!force && r.startRequested) {
9971 return;
9972 }
9973 if (r.connections.size() > 0) {
9974 if (!force) {
9975 // XXX should probably keep a count of the number of auto-create
9976 // connections directly in the service.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009977 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009978 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009979 ArrayList<ConnectionRecord> cr = it.next();
9980 for (int i=0; i<cr.size(); i++) {
9981 if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
9982 return;
9983 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009984 }
9985 }
9986 }
9987
9988 // Report to all of the connections that the service is no longer
9989 // available.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009990 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009991 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009992 ArrayList<ConnectionRecord> c = it.next();
9993 for (int i=0; i<c.size(); i++) {
9994 try {
9995 c.get(i).conn.connected(r.name, null);
9996 } catch (Exception e) {
9997 Slog.w(TAG, "Failure disconnecting service " + r.name +
9998 " to connection " + c.get(i).conn.asBinder() +
9999 " (in " + c.get(i).binding.client.processName + ")", e);
10000 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010001 }
10002 }
10003 }
10004
10005 // Tell the service that it has been unbound.
10006 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
10007 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
10008 while (it.hasNext()) {
10009 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010010 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010011 + ": hasBound=" + ibr.hasBound);
10012 if (r.app != null && r.app.thread != null && ibr.hasBound) {
10013 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010014 bumpServiceExecutingLocked(r, "bring down unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010015 updateOomAdjLocked(r.app);
10016 ibr.hasBound = false;
10017 r.app.thread.scheduleUnbindService(r,
10018 ibr.intent.getIntent());
10019 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010020 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010021 + r.shortName, e);
10022 serviceDoneExecutingLocked(r, true);
10023 }
10024 }
10025 }
10026 }
10027
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010028 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010029 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010030 System.identityHashCode(r), r.shortName,
10031 (r.app != null) ? r.app.pid : -1);
10032
10033 mServices.remove(r.name);
10034 mServicesByIntent.remove(r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010035 r.totalRestartCount = 0;
10036 unscheduleServiceRestartLocked(r);
10037
10038 // Also make sure it is not on the pending list.
10039 int N = mPendingServices.size();
10040 for (int i=0; i<N; i++) {
10041 if (mPendingServices.get(i) == r) {
10042 mPendingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010043 if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010044 i--;
10045 N--;
10046 }
10047 }
10048
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010049 r.cancelNotification();
10050 r.isForeground = false;
10051 r.foregroundId = 0;
10052 r.foregroundNoti = null;
10053
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010054 // Clear start entries.
Dianne Hackborn39792d22010-08-19 18:01:52 -070010055 r.clearDeliveredStartsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010056 r.pendingStarts.clear();
10057
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010058 if (r.app != null) {
10059 synchronized (r.stats.getBatteryStats()) {
10060 r.stats.stopLaunchedLocked();
10061 }
10062 r.app.services.remove(r);
10063 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010064 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010065 bumpServiceExecutingLocked(r, "stop");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010066 mStoppingServices.add(r);
10067 updateOomAdjLocked(r.app);
10068 r.app.thread.scheduleStopService(r);
10069 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010070 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010071 + r.shortName, e);
10072 serviceDoneExecutingLocked(r, true);
10073 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010074 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010075 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010076 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010077 TAG, "Removed service that has no process: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010078 }
10079 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010080 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010081 TAG, "Removed service that is not running: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010082 }
Vairavan Srinivasana207ce22010-12-23 13:51:48 -080010083
10084 if (r.bindings.size() > 0) {
10085 r.bindings.clear();
10086 }
10087
10088 if (r.restarter instanceof ServiceRestarter) {
10089 ((ServiceRestarter)r.restarter).setService(null);
10090 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010091 }
10092
10093 ComponentName startServiceLocked(IApplicationThread caller,
10094 Intent service, String resolvedType,
10095 int callingPid, int callingUid) {
10096 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010097 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010098 + " type=" + resolvedType + " args=" + service.getExtras());
10099
10100 if (caller != null) {
10101 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10102 if (callerApp == null) {
10103 throw new SecurityException(
10104 "Unable to find app for caller " + caller
10105 + " (pid=" + Binder.getCallingPid()
10106 + ") when starting service " + service);
10107 }
10108 }
10109
10110 ServiceLookupResult res =
10111 retrieveServiceLocked(service, resolvedType,
10112 callingPid, callingUid);
10113 if (res == null) {
10114 return null;
10115 }
10116 if (res.record == null) {
10117 return new ComponentName("!", res.permission != null
10118 ? res.permission : "private to package");
10119 }
10120 ServiceRecord r = res.record;
Dianne Hackborn39792d22010-08-19 18:01:52 -070010121 int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
10122 callingUid, r.packageName, service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010123 if (unscheduleServiceRestartLocked(r)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010124 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010125 }
10126 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010127 r.callStart = false;
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010128 r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
Dianne Hackborn39792d22010-08-19 18:01:52 -070010129 service, targetPermissionUid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010130 r.lastActivity = SystemClock.uptimeMillis();
10131 synchronized (r.stats.getBatteryStats()) {
10132 r.stats.startRunningLocked();
10133 }
10134 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
10135 return new ComponentName("!", "Service process is bad");
10136 }
10137 return r.name;
10138 }
10139 }
10140
10141 public ComponentName startService(IApplicationThread caller, Intent service,
10142 String resolvedType) {
10143 // Refuse possible leaked file descriptors
10144 if (service != null && service.hasFileDescriptors() == true) {
10145 throw new IllegalArgumentException("File descriptors passed in Intent");
10146 }
10147
10148 synchronized(this) {
10149 final int callingPid = Binder.getCallingPid();
10150 final int callingUid = Binder.getCallingUid();
10151 final long origId = Binder.clearCallingIdentity();
10152 ComponentName res = startServiceLocked(caller, service,
10153 resolvedType, callingPid, callingUid);
10154 Binder.restoreCallingIdentity(origId);
10155 return res;
10156 }
10157 }
10158
10159 ComponentName startServiceInPackage(int uid,
10160 Intent service, String resolvedType) {
10161 synchronized(this) {
10162 final long origId = Binder.clearCallingIdentity();
10163 ComponentName res = startServiceLocked(null, service,
10164 resolvedType, -1, uid);
10165 Binder.restoreCallingIdentity(origId);
10166 return res;
10167 }
10168 }
10169
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010170 private void stopServiceLocked(ServiceRecord service) {
10171 synchronized (service.stats.getBatteryStats()) {
10172 service.stats.stopRunningLocked();
10173 }
10174 service.startRequested = false;
10175 service.callStart = false;
10176 bringDownServiceLocked(service, false);
10177 }
10178
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010179 public int stopService(IApplicationThread caller, Intent service,
10180 String resolvedType) {
10181 // Refuse possible leaked file descriptors
10182 if (service != null && service.hasFileDescriptors() == true) {
10183 throw new IllegalArgumentException("File descriptors passed in Intent");
10184 }
10185
10186 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010187 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010188 + " type=" + resolvedType);
10189
10190 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10191 if (caller != null && callerApp == null) {
10192 throw new SecurityException(
10193 "Unable to find app for caller " + caller
10194 + " (pid=" + Binder.getCallingPid()
10195 + ") when stopping service " + service);
10196 }
10197
10198 // If this service is active, make sure it is stopped.
10199 ServiceLookupResult r = findServiceLocked(service, resolvedType);
10200 if (r != null) {
10201 if (r.record != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010202 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010203 try {
10204 stopServiceLocked(r.record);
10205 } finally {
10206 Binder.restoreCallingIdentity(origId);
10207 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010208 return 1;
10209 }
10210 return -1;
10211 }
10212 }
10213
10214 return 0;
10215 }
10216
10217 public IBinder peekService(Intent service, String resolvedType) {
10218 // Refuse possible leaked file descriptors
10219 if (service != null && service.hasFileDescriptors() == true) {
10220 throw new IllegalArgumentException("File descriptors passed in Intent");
10221 }
10222
10223 IBinder ret = null;
10224
10225 synchronized(this) {
10226 ServiceLookupResult r = findServiceLocked(service, resolvedType);
10227
10228 if (r != null) {
10229 // r.record is null if findServiceLocked() failed the caller permission check
10230 if (r.record == null) {
10231 throw new SecurityException(
10232 "Permission Denial: Accessing service " + r.record.name
10233 + " from pid=" + Binder.getCallingPid()
10234 + ", uid=" + Binder.getCallingUid()
10235 + " requires " + r.permission);
10236 }
10237 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
10238 if (ib != null) {
10239 ret = ib.binder;
10240 }
10241 }
10242 }
10243
10244 return ret;
10245 }
10246
10247 public boolean stopServiceToken(ComponentName className, IBinder token,
10248 int startId) {
10249 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010250 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010251 + " " + token + " startId=" + startId);
10252 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010253 if (r != null) {
10254 if (startId >= 0) {
10255 // Asked to only stop if done with all work. Note that
10256 // to avoid leaks, we will take this as dropping all
10257 // start items up to and including this one.
10258 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
10259 if (si != null) {
10260 while (r.deliveredStarts.size() > 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -070010261 ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
10262 cur.removeUriPermissionsLocked();
10263 if (cur == si) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010264 break;
10265 }
10266 }
10267 }
10268
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010269 if (r.getLastStartId() != startId) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010270 return false;
10271 }
10272
10273 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010274 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010275 + " is last, but have " + r.deliveredStarts.size()
10276 + " remaining args");
10277 }
10278 }
10279
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010280 synchronized (r.stats.getBatteryStats()) {
10281 r.stats.stopRunningLocked();
10282 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010283 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010284 }
10285 final long origId = Binder.clearCallingIdentity();
10286 bringDownServiceLocked(r, false);
10287 Binder.restoreCallingIdentity(origId);
10288 return true;
10289 }
10290 }
10291 return false;
10292 }
10293
10294 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010295 int id, Notification notification, boolean removeNotification) {
10296 final long origId = Binder.clearCallingIdentity();
10297 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010298 synchronized(this) {
10299 ServiceRecord r = findServiceLocked(className, token);
10300 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010301 if (id != 0) {
10302 if (notification == null) {
10303 throw new IllegalArgumentException("null notification");
10304 }
10305 if (r.foregroundId != id) {
10306 r.cancelNotification();
10307 r.foregroundId = id;
10308 }
10309 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
10310 r.foregroundNoti = notification;
10311 r.isForeground = true;
10312 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010313 if (r.app != null) {
10314 updateServiceForegroundLocked(r.app, true);
10315 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010316 } else {
10317 if (r.isForeground) {
10318 r.isForeground = false;
10319 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -070010320 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010321 updateServiceForegroundLocked(r.app, true);
10322 }
10323 }
10324 if (removeNotification) {
10325 r.cancelNotification();
10326 r.foregroundId = 0;
10327 r.foregroundNoti = null;
10328 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010329 }
10330 }
10331 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010332 } finally {
10333 Binder.restoreCallingIdentity(origId);
10334 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010335 }
10336
10337 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
10338 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -070010339 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010340 if (sr.isForeground) {
10341 anyForeground = true;
10342 break;
10343 }
10344 }
10345 if (anyForeground != proc.foregroundServices) {
10346 proc.foregroundServices = anyForeground;
10347 if (oomAdj) {
10348 updateOomAdjLocked();
10349 }
10350 }
10351 }
10352
10353 public int bindService(IApplicationThread caller, IBinder token,
10354 Intent service, String resolvedType,
10355 IServiceConnection connection, int flags) {
10356 // Refuse possible leaked file descriptors
10357 if (service != null && service.hasFileDescriptors() == true) {
10358 throw new IllegalArgumentException("File descriptors passed in Intent");
10359 }
10360
10361 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010362 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010363 + " type=" + resolvedType + " conn=" + connection.asBinder()
10364 + " flags=0x" + Integer.toHexString(flags));
10365 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10366 if (callerApp == null) {
10367 throw new SecurityException(
10368 "Unable to find app for caller " + caller
10369 + " (pid=" + Binder.getCallingPid()
10370 + ") when binding service " + service);
10371 }
10372
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010373 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010374 if (token != null) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -070010375 activity = mMainStack.isInStackLocked(token);
10376 if (activity == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010377 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010378 return 0;
10379 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010380 }
10381
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010382 int clientLabel = 0;
10383 PendingIntent clientIntent = null;
10384
10385 if (callerApp.info.uid == Process.SYSTEM_UID) {
10386 // Hacky kind of thing -- allow system stuff to tell us
10387 // what they are, so we can report this elsewhere for
10388 // others to know why certain services are running.
10389 try {
10390 clientIntent = (PendingIntent)service.getParcelableExtra(
10391 Intent.EXTRA_CLIENT_INTENT);
10392 } catch (RuntimeException e) {
10393 }
10394 if (clientIntent != null) {
10395 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
10396 if (clientLabel != 0) {
10397 // There are no useful extras in the intent, trash them.
10398 // System code calling with this stuff just needs to know
10399 // this will happen.
10400 service = service.cloneFilter();
10401 }
10402 }
10403 }
10404
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010405 ServiceLookupResult res =
10406 retrieveServiceLocked(service, resolvedType,
10407 Binder.getCallingPid(), Binder.getCallingUid());
10408 if (res == null) {
10409 return 0;
10410 }
10411 if (res.record == null) {
10412 return -1;
10413 }
10414 ServiceRecord s = res.record;
10415
10416 final long origId = Binder.clearCallingIdentity();
10417
10418 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010419 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010420 + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010421 }
10422
10423 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
10424 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010425 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010426
10427 IBinder binder = connection.asBinder();
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010428 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
10429 if (clist == null) {
10430 clist = new ArrayList<ConnectionRecord>();
10431 s.connections.put(binder, clist);
10432 }
10433 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010434 b.connections.add(c);
10435 if (activity != null) {
10436 if (activity.connections == null) {
10437 activity.connections = new HashSet<ConnectionRecord>();
10438 }
10439 activity.connections.add(c);
10440 }
10441 b.client.connections.add(c);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010442 clist = mServiceConnections.get(binder);
10443 if (clist == null) {
10444 clist = new ArrayList<ConnectionRecord>();
10445 mServiceConnections.put(binder, clist);
10446 }
10447 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010448
10449 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
10450 s.lastActivity = SystemClock.uptimeMillis();
10451 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
10452 return 0;
10453 }
10454 }
10455
10456 if (s.app != null) {
10457 // This could have made the service more important.
10458 updateOomAdjLocked(s.app);
10459 }
10460
Joe Onorato8a9b2202010-02-26 18:56:32 -080010461 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010462 + ": received=" + b.intent.received
10463 + " apps=" + b.intent.apps.size()
10464 + " doRebind=" + b.intent.doRebind);
10465
10466 if (s.app != null && b.intent.received) {
10467 // Service is already running, so we can immediately
10468 // publish the connection.
10469 try {
10470 c.conn.connected(s.name, b.intent.binder);
10471 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010472 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010473 + " to connection " + c.conn.asBinder()
10474 + " (in " + c.binding.client.processName + ")", e);
10475 }
10476
10477 // If this is the first app connected back to this binding,
10478 // and the service had previously asked to be told when
10479 // rebound, then do so.
10480 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
10481 requestServiceBindingLocked(s, b.intent, true);
10482 }
10483 } else if (!b.intent.requested) {
10484 requestServiceBindingLocked(s, b.intent, false);
10485 }
10486
10487 Binder.restoreCallingIdentity(origId);
10488 }
10489
10490 return 1;
10491 }
10492
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010493 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010494 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010495 IBinder binder = c.conn.asBinder();
10496 AppBindRecord b = c.binding;
10497 ServiceRecord s = b.service;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010498 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
10499 if (clist != null) {
10500 clist.remove(c);
10501 if (clist.size() == 0) {
10502 s.connections.remove(binder);
10503 }
10504 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010505 b.connections.remove(c);
10506 if (c.activity != null && c.activity != skipAct) {
10507 if (c.activity.connections != null) {
10508 c.activity.connections.remove(c);
10509 }
10510 }
10511 if (b.client != skipApp) {
10512 b.client.connections.remove(c);
10513 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010514 clist = mServiceConnections.get(binder);
10515 if (clist != null) {
10516 clist.remove(c);
10517 if (clist.size() == 0) {
10518 mServiceConnections.remove(binder);
10519 }
10520 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010521
10522 if (b.connections.size() == 0) {
10523 b.intent.apps.remove(b.client);
10524 }
10525
Joe Onorato8a9b2202010-02-26 18:56:32 -080010526 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010527 + ": shouldUnbind=" + b.intent.hasBound);
10528 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
10529 && b.intent.hasBound) {
10530 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010531 bumpServiceExecutingLocked(s, "unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010532 updateOomAdjLocked(s.app);
10533 b.intent.hasBound = false;
10534 // Assume the client doesn't want to know about a rebind;
10535 // we will deal with that later if it asks for one.
10536 b.intent.doRebind = false;
10537 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
10538 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010539 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010540 serviceDoneExecutingLocked(s, true);
10541 }
10542 }
10543
10544 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
10545 bringDownServiceLocked(s, false);
10546 }
10547 }
10548
10549 public boolean unbindService(IServiceConnection connection) {
10550 synchronized (this) {
10551 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010552 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010553 ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
10554 if (clist == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010555 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010556 + connection.asBinder());
10557 return false;
10558 }
10559
10560 final long origId = Binder.clearCallingIdentity();
10561
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010562 while (clist.size() > 0) {
10563 ConnectionRecord r = clist.get(0);
10564 removeConnectionLocked(r, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010565
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010566 if (r.binding.service.app != null) {
10567 // This could have made the service less important.
10568 updateOomAdjLocked(r.binding.service.app);
10569 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010570 }
10571
10572 Binder.restoreCallingIdentity(origId);
10573 }
10574
10575 return true;
10576 }
10577
10578 public void publishService(IBinder token, Intent intent, IBinder service) {
10579 // Refuse possible leaked file descriptors
10580 if (intent != null && intent.hasFileDescriptors() == true) {
10581 throw new IllegalArgumentException("File descriptors passed in Intent");
10582 }
10583
10584 synchronized(this) {
10585 if (!(token instanceof ServiceRecord)) {
10586 throw new IllegalArgumentException("Invalid service token");
10587 }
10588 ServiceRecord r = (ServiceRecord)token;
10589
10590 final long origId = Binder.clearCallingIdentity();
10591
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010592 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010593 + " " + intent + ": " + service);
10594 if (r != null) {
10595 Intent.FilterComparison filter
10596 = new Intent.FilterComparison(intent);
10597 IntentBindRecord b = r.bindings.get(filter);
10598 if (b != null && !b.received) {
10599 b.binder = service;
10600 b.requested = true;
10601 b.received = true;
10602 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010603 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010604 = r.connections.values().iterator();
10605 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010606 ArrayList<ConnectionRecord> clist = it.next();
10607 for (int i=0; i<clist.size(); i++) {
10608 ConnectionRecord c = clist.get(i);
10609 if (!filter.equals(c.binding.intent.intent)) {
10610 if (DEBUG_SERVICE) Slog.v(
10611 TAG, "Not publishing to: " + c);
10612 if (DEBUG_SERVICE) Slog.v(
10613 TAG, "Bound intent: " + c.binding.intent.intent);
10614 if (DEBUG_SERVICE) Slog.v(
10615 TAG, "Published intent: " + intent);
10616 continue;
10617 }
10618 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
10619 try {
10620 c.conn.connected(r.name, service);
10621 } catch (Exception e) {
10622 Slog.w(TAG, "Failure sending service " + r.name +
10623 " to connection " + c.conn.asBinder() +
10624 " (in " + c.binding.client.processName + ")", e);
10625 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010626 }
10627 }
10628 }
10629 }
10630
10631 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
10632
10633 Binder.restoreCallingIdentity(origId);
10634 }
10635 }
10636 }
10637
10638 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
10639 // Refuse possible leaked file descriptors
10640 if (intent != null && intent.hasFileDescriptors() == true) {
10641 throw new IllegalArgumentException("File descriptors passed in Intent");
10642 }
10643
10644 synchronized(this) {
10645 if (!(token instanceof ServiceRecord)) {
10646 throw new IllegalArgumentException("Invalid service token");
10647 }
10648 ServiceRecord r = (ServiceRecord)token;
10649
10650 final long origId = Binder.clearCallingIdentity();
10651
10652 if (r != null) {
10653 Intent.FilterComparison filter
10654 = new Intent.FilterComparison(intent);
10655 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010656 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010657 + " at " + b + ": apps="
10658 + (b != null ? b.apps.size() : 0));
10659 if (b != null) {
10660 if (b.apps.size() > 0) {
10661 // Applications have already bound since the last
10662 // unbind, so just rebind right here.
10663 requestServiceBindingLocked(r, b, true);
10664 } else {
10665 // Note to tell the service the next time there is
10666 // a new client.
10667 b.doRebind = true;
10668 }
10669 }
10670
10671 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
10672
10673 Binder.restoreCallingIdentity(origId);
10674 }
10675 }
10676 }
10677
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010678 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010679 synchronized(this) {
10680 if (!(token instanceof ServiceRecord)) {
10681 throw new IllegalArgumentException("Invalid service token");
10682 }
10683 ServiceRecord r = (ServiceRecord)token;
10684 boolean inStopping = mStoppingServices.contains(token);
10685 if (r != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010686 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010687 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010688 + " with incorrect token: given " + token
10689 + ", expected " + r);
10690 return;
10691 }
10692
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010693 if (type == 1) {
10694 // This is a call from a service start... take care of
10695 // book-keeping.
10696 r.callStart = true;
10697 switch (res) {
10698 case Service.START_STICKY_COMPATIBILITY:
10699 case Service.START_STICKY: {
10700 // We are done with the associated start arguments.
10701 r.findDeliveredStart(startId, true);
10702 // Don't stop if killed.
10703 r.stopIfKilled = false;
10704 break;
10705 }
10706 case Service.START_NOT_STICKY: {
10707 // We are done with the associated start arguments.
10708 r.findDeliveredStart(startId, true);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010709 if (r.getLastStartId() == startId) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010710 // There is no more work, and this service
10711 // doesn't want to hang around if killed.
10712 r.stopIfKilled = true;
10713 }
10714 break;
10715 }
10716 case Service.START_REDELIVER_INTENT: {
10717 // We'll keep this item until they explicitly
10718 // call stop for it, but keep track of the fact
10719 // that it was delivered.
10720 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
10721 if (si != null) {
10722 si.deliveryCount = 0;
10723 si.doneExecutingCount++;
10724 // Don't stop if killed.
10725 r.stopIfKilled = true;
10726 }
10727 break;
10728 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010729 case Service.START_TASK_REMOVED_COMPLETE: {
10730 // Special processing for onTaskRemoved(). Don't
10731 // impact normal onStartCommand() processing.
10732 r.findDeliveredStart(startId, true);
10733 break;
10734 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010735 default:
10736 throw new IllegalArgumentException(
10737 "Unknown service start result: " + res);
10738 }
10739 if (res == Service.START_STICKY_COMPATIBILITY) {
10740 r.callStart = false;
10741 }
10742 }
10743
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010744 final long origId = Binder.clearCallingIdentity();
10745 serviceDoneExecutingLocked(r, inStopping);
10746 Binder.restoreCallingIdentity(origId);
10747 } else {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010748 Slog.w(TAG, "Done executing unknown service from pid "
10749 + Binder.getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010750 }
10751 }
10752 }
10753
10754 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010755 if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
10756 + ": nesting=" + r.executeNesting
10757 + ", inStopping=" + inStopping + ", app=" + r.app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070010758 else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010759 r.executeNesting--;
10760 if (r.executeNesting <= 0 && r.app != null) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010761 if (DEBUG_SERVICE) Slog.v(TAG,
10762 "Nesting at 0 of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010763 r.app.executingServices.remove(r);
10764 if (r.app.executingServices.size() == 0) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010765 if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,
10766 "No more executingServices of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010767 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
10768 }
10769 if (inStopping) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010770 if (DEBUG_SERVICE) Slog.v(TAG,
10771 "doneExecuting remove stopping " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010772 mStoppingServices.remove(r);
Mattias Petersson3996b412010-10-27 09:32:51 +020010773 r.bindings.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010774 }
10775 updateOomAdjLocked(r.app);
10776 }
10777 }
10778
10779 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010780 String anrMessage = null;
10781
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010782 synchronized(this) {
10783 if (proc.executingServices.size() == 0 || proc.thread == null) {
10784 return;
10785 }
10786 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
10787 Iterator<ServiceRecord> it = proc.executingServices.iterator();
10788 ServiceRecord timeout = null;
10789 long nextTime = 0;
10790 while (it.hasNext()) {
10791 ServiceRecord sr = it.next();
10792 if (sr.executingStart < maxTime) {
10793 timeout = sr;
10794 break;
10795 }
10796 if (sr.executingStart > nextTime) {
10797 nextTime = sr.executingStart;
10798 }
10799 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010800 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010801 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010802 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010803 } else {
10804 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
10805 msg.obj = proc;
10806 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
10807 }
10808 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010809
10810 if (anrMessage != null) {
10811 appNotResponding(proc, null, null, anrMessage);
10812 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010813 }
10814
10815 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070010816 // BACKUP AND RESTORE
10817 // =========================================================
10818
10819 // Cause the target app to be launched if necessary and its backup agent
10820 // instantiated. The backup agent will invoke backupAgentCreated() on the
10821 // activity manager to announce its creation.
10822 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010823 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070010824 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
10825
10826 synchronized(this) {
10827 // !!! TODO: currently no check here that we're already bound
10828 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
10829 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
10830 synchronized (stats) {
10831 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
10832 }
10833
Dianne Hackborne7f97212011-02-24 14:40:20 -080010834 // Backup agent is now in use, its package can't be stopped.
10835 try {
10836 AppGlobals.getPackageManager().setPackageStoppedState(
10837 app.packageName, false);
10838 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -080010839 } catch (IllegalArgumentException e) {
10840 Slog.w(TAG, "Failed trying to unstop package "
10841 + app.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -080010842 }
10843
Christopher Tate181fafa2009-05-14 11:12:14 -070010844 BackupRecord r = new BackupRecord(ss, app, backupMode);
Christopher Tate4a627c72011-04-01 14:43:32 -070010845 ComponentName hostingName = (backupMode == IApplicationThread.BACKUP_MODE_INCREMENTAL)
10846 ? new ComponentName(app.packageName, app.backupAgentName)
10847 : new ComponentName("android", "FullBackupAgent");
Christopher Tate181fafa2009-05-14 11:12:14 -070010848 // startProcessLocked() returns existing proc's record if it's already running
10849 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010850 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070010851 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010852 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070010853 return false;
10854 }
10855
10856 r.app = proc;
10857 mBackupTarget = r;
10858 mBackupAppName = app.packageName;
10859
Christopher Tate6fa95972009-06-05 18:43:55 -070010860 // Try not to kill the process during backup
10861 updateOomAdjLocked(proc);
10862
Christopher Tate181fafa2009-05-14 11:12:14 -070010863 // If the process is already attached, schedule the creation of the backup agent now.
10864 // If it is not yet live, this will be done when it attaches to the framework.
10865 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010866 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070010867 try {
Dianne Hackborne2515ee2011-04-27 18:52:56 -040010868 proc.thread.scheduleCreateBackupAgent(app,
10869 compatibilityInfoForPackageLocked(app), backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070010870 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070010871 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070010872 }
10873 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010874 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070010875 }
10876 // Invariants: at this point, the target app process exists and the application
10877 // is either already running or in the process of coming up. mBackupTarget and
10878 // mBackupAppName describe the app, so that when it binds back to the AM we
10879 // know that it's scheduled for a backup-agent operation.
10880 }
10881
10882 return true;
10883 }
10884
10885 // A backup agent has just come up
10886 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010887 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070010888 + " = " + agent);
10889
10890 synchronized(this) {
10891 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010892 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070010893 return;
10894 }
Dianne Hackborn06740692010-09-22 22:46:21 -070010895 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010896
Dianne Hackborn06740692010-09-22 22:46:21 -070010897 long oldIdent = Binder.clearCallingIdentity();
10898 try {
10899 IBackupManager bm = IBackupManager.Stub.asInterface(
10900 ServiceManager.getService(Context.BACKUP_SERVICE));
10901 bm.agentConnected(agentPackageName, agent);
10902 } catch (RemoteException e) {
10903 // can't happen; the backup manager service is local
10904 } catch (Exception e) {
10905 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
10906 e.printStackTrace();
10907 } finally {
10908 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070010909 }
10910 }
10911
10912 // done with this agent
10913 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010914 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070010915 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010916 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070010917 return;
10918 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010919
10920 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070010921 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010922 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070010923 return;
10924 }
10925
Christopher Tate181fafa2009-05-14 11:12:14 -070010926 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010927 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070010928 return;
10929 }
10930
Christopher Tate6fa95972009-06-05 18:43:55 -070010931 ProcessRecord proc = mBackupTarget.app;
10932 mBackupTarget = null;
10933 mBackupAppName = null;
10934
10935 // Not backing this app up any more; reset its OOM adjustment
10936 updateOomAdjLocked(proc);
10937
Christopher Tatec7b31e32009-06-10 15:49:30 -070010938 // If the app crashed during backup, 'thread' will be null here
10939 if (proc.thread != null) {
10940 try {
Dianne Hackborne2515ee2011-04-27 18:52:56 -040010941 proc.thread.scheduleDestroyBackupAgent(appInfo,
10942 compatibilityInfoForPackageLocked(appInfo));
Christopher Tatec7b31e32009-06-10 15:49:30 -070010943 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010944 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070010945 e.printStackTrace();
10946 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010947 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010948 }
10949 }
10950 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010951 // BROADCASTS
10952 // =========================================================
10953
Josh Bartel7f208742010-02-25 11:01:44 -060010954 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010955 List cur) {
10956 final ContentResolver resolver = mContext.getContentResolver();
10957 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
10958 if (list == null) {
10959 return cur;
10960 }
10961 int N = list.size();
10962 for (int i=0; i<N; i++) {
10963 Intent intent = list.get(i);
10964 if (filter.match(resolver, intent, true, TAG) >= 0) {
10965 if (cur == null) {
10966 cur = new ArrayList<Intent>();
10967 }
10968 cur.add(intent);
10969 }
10970 }
10971 return cur;
10972 }
10973
10974 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010975 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010976 + mBroadcastsScheduled);
10977
10978 if (mBroadcastsScheduled) {
10979 return;
10980 }
10981 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
10982 mBroadcastsScheduled = true;
10983 }
10984
Dianne Hackborn6c418d52011-06-29 14:05:33 -070010985 public Intent registerReceiver(IApplicationThread caller, String callerPackage,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010986 IIntentReceiver receiver, IntentFilter filter, String permission) {
10987 synchronized(this) {
10988 ProcessRecord callerApp = null;
10989 if (caller != null) {
10990 callerApp = getRecordForAppLocked(caller);
10991 if (callerApp == null) {
10992 throw new SecurityException(
10993 "Unable to find app for caller " + caller
10994 + " (pid=" + Binder.getCallingPid()
10995 + ") when registering receiver " + receiver);
10996 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -070010997 if (callerApp.info.uid != Process.SYSTEM_UID &&
10998 !callerApp.pkgList.contains(callerPackage)) {
10999 throw new SecurityException("Given caller package " + callerPackage
11000 + " is not running in process " + callerApp);
11001 }
11002 } else {
11003 callerPackage = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011004 }
11005
11006 List allSticky = null;
11007
11008 // Look for any matching sticky broadcasts...
11009 Iterator actions = filter.actionsIterator();
11010 if (actions != null) {
11011 while (actions.hasNext()) {
11012 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -060011013 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011014 }
11015 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060011016 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011017 }
11018
11019 // The first sticky in the list is returned directly back to
11020 // the client.
11021 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
11022
Joe Onorato8a9b2202010-02-26 18:56:32 -080011023 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011024 + ": " + sticky);
11025
11026 if (receiver == null) {
11027 return sticky;
11028 }
11029
11030 ReceiverList rl
11031 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
11032 if (rl == null) {
11033 rl = new ReceiverList(this, callerApp,
11034 Binder.getCallingPid(),
11035 Binder.getCallingUid(), receiver);
11036 if (rl.app != null) {
11037 rl.app.receivers.add(rl);
11038 } else {
11039 try {
11040 receiver.asBinder().linkToDeath(rl, 0);
11041 } catch (RemoteException e) {
11042 return sticky;
11043 }
11044 rl.linkedToDeath = true;
11045 }
11046 mRegisteredReceivers.put(receiver.asBinder(), rl);
11047 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -070011048 BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage, permission);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011049 rl.add(bf);
11050 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011051 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011052 }
11053 mReceiverResolver.addFilter(bf);
11054
11055 // Enqueue broadcasts for all existing stickies that match
11056 // this filter.
11057 if (allSticky != null) {
11058 ArrayList receivers = new ArrayList();
11059 receivers.add(bf);
11060
11061 int N = allSticky.size();
11062 for (int i=0; i<N; i++) {
11063 Intent intent = (Intent)allSticky.get(i);
11064 BroadcastRecord r = new BroadcastRecord(intent, null,
11065 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011066 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011067 if (mParallelBroadcasts.size() == 0) {
11068 scheduleBroadcastsLocked();
11069 }
11070 mParallelBroadcasts.add(r);
11071 }
11072 }
11073
11074 return sticky;
11075 }
11076 }
11077
11078 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011079 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011080
11081 boolean doNext = false;
11082
11083 synchronized(this) {
11084 ReceiverList rl
11085 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
11086 if (rl != null) {
11087 if (rl.curBroadcast != null) {
11088 BroadcastRecord r = rl.curBroadcast;
11089 doNext = finishReceiverLocked(
11090 receiver.asBinder(), r.resultCode, r.resultData,
11091 r.resultExtras, r.resultAbort, true);
11092 }
11093
11094 if (rl.app != null) {
11095 rl.app.receivers.remove(rl);
11096 }
11097 removeReceiverLocked(rl);
11098 if (rl.linkedToDeath) {
11099 rl.linkedToDeath = false;
11100 rl.receiver.asBinder().unlinkToDeath(rl, 0);
11101 }
11102 }
11103 }
11104
11105 if (!doNext) {
11106 return;
11107 }
11108
11109 final long origId = Binder.clearCallingIdentity();
11110 processNextBroadcast(false);
11111 trimApplications();
11112 Binder.restoreCallingIdentity(origId);
11113 }
11114
11115 void removeReceiverLocked(ReceiverList rl) {
11116 mRegisteredReceivers.remove(rl.receiver.asBinder());
11117 int N = rl.size();
11118 for (int i=0; i<N; i++) {
11119 mReceiverResolver.removeFilter(rl.get(i));
11120 }
11121 }
11122
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070011123 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
11124 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
11125 ProcessRecord r = mLruProcesses.get(i);
11126 if (r.thread != null) {
11127 try {
11128 r.thread.dispatchPackageBroadcast(cmd, packages);
11129 } catch (RemoteException ex) {
11130 }
11131 }
11132 }
11133 }
11134
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011135 private final int broadcastIntentLocked(ProcessRecord callerApp,
11136 String callerPackage, Intent intent, String resolvedType,
11137 IIntentReceiver resultTo, int resultCode, String resultData,
11138 Bundle map, String requiredPermission,
11139 boolean ordered, boolean sticky, int callingPid, int callingUid) {
11140 intent = new Intent(intent);
11141
Dianne Hackborne7f97212011-02-24 14:40:20 -080011142 // By default broadcasts do not go to stopped apps.
11143 intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
11144
Joe Onorato8a9b2202010-02-26 18:56:32 -080011145 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011146 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
11147 + " ordered=" + ordered);
11148 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011149 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011150 }
11151
11152 // Handle special intents: if this broadcast is from the package
11153 // manager about a package being removed, we need to remove all of
11154 // its activities from the history stack.
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011155 final boolean uidRemoved = Intent.ACTION_UID_REMOVED.equals(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011156 intent.getAction());
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011157 if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
11158 || Intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080011159 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011160 || uidRemoved) {
11161 if (checkComponentPermission(
11162 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011163 callingPid, callingUid, -1, true)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011164 == PackageManager.PERMISSION_GRANTED) {
11165 if (uidRemoved) {
11166 final Bundle intentExtras = intent.getExtras();
11167 final int uid = intentExtras != null
11168 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
11169 if (uid >= 0) {
11170 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
11171 synchronized (bs) {
11172 bs.removeUidStatsLocked(uid);
11173 }
11174 }
11175 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011176 // If resources are unvailble just force stop all
11177 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080011178 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011179 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
11180 if (list != null && (list.length > 0)) {
11181 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011182 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011183 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070011184 sendPackageBroadcastLocked(
11185 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011186 }
11187 } else {
11188 Uri data = intent.getData();
11189 String ssp;
11190 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
11191 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
11192 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011193 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070011194 }
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011195 if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070011196 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
11197 new String[] {ssp});
11198 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011199 }
11200 }
11201 }
11202 } else {
11203 String msg = "Permission Denial: " + intent.getAction()
11204 + " broadcast from " + callerPackage + " (pid=" + callingPid
11205 + ", uid=" + callingUid + ")"
11206 + " requires "
11207 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011208 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011209 throw new SecurityException(msg);
11210 }
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011211
11212 // Special case for adding a package: by default turn on compatibility
11213 // mode.
11214 } else if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())) {
Dianne Hackborn8ea5e1d2011-05-27 16:45:31 -070011215 Uri data = intent.getData();
11216 String ssp;
11217 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
11218 mCompatModePackages.handlePackageAddedLocked(ssp,
11219 intent.getBooleanExtra(Intent.EXTRA_REPLACING, false));
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011220 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011221 }
11222
11223 /*
11224 * If this is the time zone changed action, queue up a message that will reset the timezone
11225 * of all currently running processes. This message will get queued up before the broadcast
11226 * happens.
11227 */
11228 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
11229 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
11230 }
11231
Robert Greenwalt03595d02010-11-02 14:08:23 -070011232 if (intent.ACTION_CLEAR_DNS_CACHE.equals(intent.getAction())) {
11233 mHandler.sendEmptyMessage(CLEAR_DNS_CACHE);
11234 }
11235
Robert Greenwalt434203a2010-10-11 16:00:27 -070011236 if (Proxy.PROXY_CHANGE_ACTION.equals(intent.getAction())) {
11237 ProxyProperties proxy = intent.getParcelableExtra("proxy");
11238 mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY, proxy));
11239 }
11240
Dianne Hackborn854060af2009-07-09 18:14:31 -070011241 /*
11242 * Prevent non-system code (defined here to be non-persistent
11243 * processes) from sending protected broadcasts.
11244 */
11245 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
11246 || callingUid == Process.SHELL_UID || callingUid == 0) {
11247 // Always okay.
11248 } else if (callerApp == null || !callerApp.persistent) {
11249 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011250 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -070011251 intent.getAction())) {
11252 String msg = "Permission Denial: not allowed to send broadcast "
11253 + intent.getAction() + " from pid="
11254 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011255 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070011256 throw new SecurityException(msg);
11257 }
11258 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011259 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070011260 return BROADCAST_SUCCESS;
11261 }
11262 }
11263
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011264 // Add to the sticky list if requested.
11265 if (sticky) {
11266 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
11267 callingPid, callingUid)
11268 != PackageManager.PERMISSION_GRANTED) {
11269 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
11270 + callingPid + ", uid=" + callingUid
11271 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011272 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011273 throw new SecurityException(msg);
11274 }
11275 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011276 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011277 + " and enforce permission " + requiredPermission);
11278 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
11279 }
11280 if (intent.getComponent() != null) {
11281 throw new SecurityException(
11282 "Sticky broadcasts can't target a specific component");
11283 }
11284 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
11285 if (list == null) {
11286 list = new ArrayList<Intent>();
11287 mStickyBroadcasts.put(intent.getAction(), list);
11288 }
11289 int N = list.size();
11290 int i;
11291 for (i=0; i<N; i++) {
11292 if (intent.filterEquals(list.get(i))) {
11293 // This sticky already exists, replace it.
11294 list.set(i, new Intent(intent));
11295 break;
11296 }
11297 }
11298 if (i >= N) {
11299 list.add(new Intent(intent));
11300 }
11301 }
11302
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011303 // Figure out who all will receive this broadcast.
11304 List receivers = null;
11305 List<BroadcastFilter> registeredReceivers = null;
11306 try {
11307 if (intent.getComponent() != null) {
11308 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011309 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070011310 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011311 if (ai != null) {
11312 receivers = new ArrayList();
11313 ResolveInfo ri = new ResolveInfo();
11314 ri.activityInfo = ai;
11315 receivers.add(ri);
11316 }
11317 } else {
11318 // Need to resolve the intent to interested receivers...
11319 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
11320 == 0) {
11321 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011322 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011323 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011324 }
Mihai Preda074edef2009-05-18 17:13:31 +020011325 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011326 }
11327 } catch (RemoteException ex) {
11328 // pm is in same process, this will never happen.
11329 }
11330
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011331 final boolean replacePending =
11332 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
11333
Joe Onorato8a9b2202010-02-26 18:56:32 -080011334 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011335 + " replacePending=" + replacePending);
11336
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011337 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
11338 if (!ordered && NR > 0) {
11339 // If we are not serializing this broadcast, then send the
11340 // registered receivers separately so they don't wait for the
11341 // components to be launched.
11342 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
11343 callerPackage, callingPid, callingUid, requiredPermission,
11344 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011345 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011346 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011347 TAG, "Enqueueing parallel broadcast " + r
11348 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011349 boolean replaced = false;
11350 if (replacePending) {
11351 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
11352 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011353 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011354 "***** DROPPING PARALLEL: " + intent);
11355 mParallelBroadcasts.set(i, r);
11356 replaced = true;
11357 break;
11358 }
11359 }
11360 }
11361 if (!replaced) {
11362 mParallelBroadcasts.add(r);
11363 scheduleBroadcastsLocked();
11364 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011365 registeredReceivers = null;
11366 NR = 0;
11367 }
11368
11369 // Merge into one list.
11370 int ir = 0;
11371 if (receivers != null) {
11372 // A special case for PACKAGE_ADDED: do not allow the package
11373 // being added to see this broadcast. This prevents them from
11374 // using this as a back door to get run as soon as they are
11375 // installed. Maybe in the future we want to have a special install
11376 // broadcast or such for apps, but we'd like to deliberately make
11377 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011378 String skipPackages[] = null;
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011379 if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
11380 || Intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
11381 || Intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011382 Uri data = intent.getData();
11383 if (data != null) {
11384 String pkgName = data.getSchemeSpecificPart();
11385 if (pkgName != null) {
11386 skipPackages = new String[] { pkgName };
11387 }
11388 }
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011389 } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011390 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070011391 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011392 if (skipPackages != null && (skipPackages.length > 0)) {
11393 for (String skipPackage : skipPackages) {
11394 if (skipPackage != null) {
11395 int NT = receivers.size();
11396 for (int it=0; it<NT; it++) {
11397 ResolveInfo curt = (ResolveInfo)receivers.get(it);
11398 if (curt.activityInfo.packageName.equals(skipPackage)) {
11399 receivers.remove(it);
11400 it--;
11401 NT--;
11402 }
11403 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011404 }
11405 }
11406 }
11407
11408 int NT = receivers != null ? receivers.size() : 0;
11409 int it = 0;
11410 ResolveInfo curt = null;
11411 BroadcastFilter curr = null;
11412 while (it < NT && ir < NR) {
11413 if (curt == null) {
11414 curt = (ResolveInfo)receivers.get(it);
11415 }
11416 if (curr == null) {
11417 curr = registeredReceivers.get(ir);
11418 }
11419 if (curr.getPriority() >= curt.priority) {
11420 // Insert this broadcast record into the final list.
11421 receivers.add(it, curr);
11422 ir++;
11423 curr = null;
11424 it++;
11425 NT++;
11426 } else {
11427 // Skip to the next ResolveInfo in the final list.
11428 it++;
11429 curt = null;
11430 }
11431 }
11432 }
11433 while (ir < NR) {
11434 if (receivers == null) {
11435 receivers = new ArrayList();
11436 }
11437 receivers.add(registeredReceivers.get(ir));
11438 ir++;
11439 }
11440
11441 if ((receivers != null && receivers.size() > 0)
11442 || resultTo != null) {
11443 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
11444 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011445 receivers, resultTo, resultCode, resultData, map, ordered,
11446 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011447 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011448 TAG, "Enqueueing ordered broadcast " + r
11449 + ": prev had " + mOrderedBroadcasts.size());
11450 if (DEBUG_BROADCAST) {
11451 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011452 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011453 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011454 boolean replaced = false;
11455 if (replacePending) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011456 for (int i=mOrderedBroadcasts.size()-1; i>0; i--) {
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011457 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011458 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011459 "***** DROPPING ORDERED: " + intent);
11460 mOrderedBroadcasts.set(i, r);
11461 replaced = true;
11462 break;
11463 }
11464 }
11465 }
11466 if (!replaced) {
11467 mOrderedBroadcasts.add(r);
11468 scheduleBroadcastsLocked();
11469 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011470 }
11471
11472 return BROADCAST_SUCCESS;
11473 }
11474
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011475 final Intent verifyBroadcastLocked(Intent intent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011476 // Refuse possible leaked file descriptors
11477 if (intent != null && intent.hasFileDescriptors() == true) {
11478 throw new IllegalArgumentException("File descriptors passed in Intent");
11479 }
11480
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011481 int flags = intent.getFlags();
11482
11483 if (!mProcessesReady) {
11484 // if the caller really truly claims to know what they're doing, go
11485 // ahead and allow the broadcast without launching any receivers
11486 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
11487 intent = new Intent(intent);
11488 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
11489 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
11490 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
11491 + " before boot completion");
11492 throw new IllegalStateException("Cannot broadcast before boot completed");
11493 }
11494 }
11495
11496 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
11497 throw new IllegalArgumentException(
11498 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
11499 }
11500
11501 return intent;
11502 }
11503
11504 public final int broadcastIntent(IApplicationThread caller,
11505 Intent intent, String resolvedType, IIntentReceiver resultTo,
11506 int resultCode, String resultData, Bundle map,
11507 String requiredPermission, boolean serialized, boolean sticky) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011508 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011509 intent = verifyBroadcastLocked(intent);
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011510
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011511 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11512 final int callingPid = Binder.getCallingPid();
11513 final int callingUid = Binder.getCallingUid();
11514 final long origId = Binder.clearCallingIdentity();
11515 int res = broadcastIntentLocked(callerApp,
11516 callerApp != null ? callerApp.info.packageName : null,
11517 intent, resolvedType, resultTo,
11518 resultCode, resultData, map, requiredPermission, serialized,
11519 sticky, callingPid, callingUid);
11520 Binder.restoreCallingIdentity(origId);
11521 return res;
11522 }
11523 }
11524
11525 int broadcastIntentInPackage(String packageName, int uid,
11526 Intent intent, String resolvedType, IIntentReceiver resultTo,
11527 int resultCode, String resultData, Bundle map,
11528 String requiredPermission, boolean serialized, boolean sticky) {
11529 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011530 intent = verifyBroadcastLocked(intent);
11531
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011532 final long origId = Binder.clearCallingIdentity();
11533 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
11534 resultTo, resultCode, resultData, map, requiredPermission,
11535 serialized, sticky, -1, uid);
11536 Binder.restoreCallingIdentity(origId);
11537 return res;
11538 }
11539 }
11540
11541 public final void unbroadcastIntent(IApplicationThread caller,
11542 Intent intent) {
11543 // Refuse possible leaked file descriptors
11544 if (intent != null && intent.hasFileDescriptors() == true) {
11545 throw new IllegalArgumentException("File descriptors passed in Intent");
11546 }
11547
11548 synchronized(this) {
11549 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
11550 != PackageManager.PERMISSION_GRANTED) {
11551 String msg = "Permission Denial: unbroadcastIntent() from pid="
11552 + Binder.getCallingPid()
11553 + ", uid=" + Binder.getCallingUid()
11554 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011555 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011556 throw new SecurityException(msg);
11557 }
11558 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
11559 if (list != null) {
11560 int N = list.size();
11561 int i;
11562 for (i=0; i<N; i++) {
11563 if (intent.filterEquals(list.get(i))) {
11564 list.remove(i);
11565 break;
11566 }
11567 }
11568 }
11569 }
11570 }
11571
11572 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
11573 String resultData, Bundle resultExtras, boolean resultAbort,
11574 boolean explicit) {
11575 if (mOrderedBroadcasts.size() == 0) {
11576 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011577 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011578 }
11579 return false;
11580 }
11581 BroadcastRecord r = mOrderedBroadcasts.get(0);
11582 if (r.receiver == null) {
11583 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011584 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011585 }
11586 return false;
11587 }
11588 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011589 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011590 return false;
11591 }
11592 int state = r.state;
Dianne Hackbornce86ba82011-07-13 19:33:41 -070011593 r.state = BroadcastRecord.IDLE;
11594 if (state == BroadcastRecord.IDLE) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011595 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011596 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011597 }
11598 }
11599 r.receiver = null;
11600 r.intent.setComponent(null);
11601 if (r.curApp != null) {
11602 r.curApp.curReceiver = null;
11603 }
11604 if (r.curFilter != null) {
11605 r.curFilter.receiverList.curBroadcast = null;
11606 }
11607 r.curFilter = null;
11608 r.curApp = null;
11609 r.curComponent = null;
11610 r.curReceiver = null;
11611 mPendingBroadcast = null;
11612
11613 r.resultCode = resultCode;
11614 r.resultData = resultData;
11615 r.resultExtras = resultExtras;
11616 r.resultAbort = resultAbort;
11617
11618 // We will process the next receiver right now if this is finishing
11619 // an app receiver (which is always asynchronous) or after we have
11620 // come back from calling a receiver.
11621 return state == BroadcastRecord.APP_RECEIVE
11622 || state == BroadcastRecord.CALL_DONE_RECEIVE;
11623 }
11624
11625 public void finishReceiver(IBinder who, int resultCode, String resultData,
11626 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011627 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011628
11629 // Refuse possible leaked file descriptors
11630 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
11631 throw new IllegalArgumentException("File descriptors passed in Bundle");
11632 }
11633
11634 boolean doNext;
11635
11636 final long origId = Binder.clearCallingIdentity();
11637
11638 synchronized(this) {
11639 doNext = finishReceiverLocked(
11640 who, resultCode, resultData, resultExtras, resultAbort, true);
11641 }
11642
11643 if (doNext) {
11644 processNextBroadcast(false);
11645 }
11646 trimApplications();
11647
11648 Binder.restoreCallingIdentity(origId);
11649 }
11650
Jeff Brown4d94a762010-09-23 11:33:28 -070011651 private final void logBroadcastReceiverDiscardLocked(BroadcastRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011652 if (r.nextReceiver > 0) {
11653 Object curReceiver = r.receivers.get(r.nextReceiver-1);
11654 if (curReceiver instanceof BroadcastFilter) {
11655 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080011656 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011657 System.identityHashCode(r),
11658 r.intent.getAction(),
11659 r.nextReceiver - 1,
11660 System.identityHashCode(bf));
11661 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080011662 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011663 System.identityHashCode(r),
11664 r.intent.getAction(),
11665 r.nextReceiver - 1,
11666 ((ResolveInfo)curReceiver).toString());
11667 }
11668 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011669 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011670 + r);
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,
11675 "NONE");
11676 }
11677 }
11678
Jeff Brown4d94a762010-09-23 11:33:28 -070011679 private final void setBroadcastTimeoutLocked(long timeoutTime) {
11680 if (! mPendingBroadcastTimeoutMessage) {
11681 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
11682 mHandler.sendMessageAtTime(msg, timeoutTime);
11683 mPendingBroadcastTimeoutMessage = true;
11684 }
11685 }
11686
11687 private final void cancelBroadcastTimeoutLocked() {
11688 if (mPendingBroadcastTimeoutMessage) {
11689 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
11690 mPendingBroadcastTimeoutMessage = false;
11691 }
11692 }
11693
11694 private final void broadcastTimeoutLocked(boolean fromMsg) {
11695 if (fromMsg) {
11696 mPendingBroadcastTimeoutMessage = false;
11697 }
11698
11699 if (mOrderedBroadcasts.size() == 0) {
11700 return;
11701 }
11702
11703 long now = SystemClock.uptimeMillis();
11704 BroadcastRecord r = mOrderedBroadcasts.get(0);
11705 if (fromMsg) {
11706 if (mDidDexOpt) {
11707 // Delay timeouts until dexopt finishes.
11708 mDidDexOpt = false;
11709 long timeoutTime = SystemClock.uptimeMillis() + BROADCAST_TIMEOUT;
11710 setBroadcastTimeoutLocked(timeoutTime);
11711 return;
11712 }
11713 if (! mProcessesReady) {
11714 // Only process broadcast timeouts if the system is ready. That way
11715 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
11716 // to do heavy lifting for system up.
11717 return;
11718 }
11719
11720 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
11721 if (timeoutTime > now) {
11722 // We can observe premature timeouts because we do not cancel and reset the
11723 // broadcast timeout message after each receiver finishes. Instead, we set up
11724 // an initial timeout then kick it down the road a little further as needed
11725 // when it expires.
11726 if (DEBUG_BROADCAST) Slog.v(TAG,
11727 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
11728 + timeoutTime);
11729 setBroadcastTimeoutLocked(timeoutTime);
11730 return;
11731 }
11732 }
11733
11734 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver
11735 + ", started " + (now - r.receiverTime) + "ms ago");
11736 r.receiverTime = now;
11737 r.anrCount++;
11738
11739 // Current receiver has passed its expiration date.
11740 if (r.nextReceiver <= 0) {
11741 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
11742 return;
11743 }
11744
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011745 ProcessRecord app = null;
11746 String anrMessage = null;
11747
Jeff Brown4d94a762010-09-23 11:33:28 -070011748 Object curReceiver = r.receivers.get(r.nextReceiver-1);
11749 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
11750 logBroadcastReceiverDiscardLocked(r);
11751 if (curReceiver instanceof BroadcastFilter) {
11752 BroadcastFilter bf = (BroadcastFilter)curReceiver;
11753 if (bf.receiverList.pid != 0
11754 && bf.receiverList.pid != MY_PID) {
11755 synchronized (this.mPidsSelfLocked) {
11756 app = this.mPidsSelfLocked.get(
11757 bf.receiverList.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011758 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011759 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011760 } else {
11761 app = r.curApp;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011762 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011763
Jeff Brown4d94a762010-09-23 11:33:28 -070011764 if (app != null) {
11765 anrMessage = "Broadcast of " + r.intent.toString();
11766 }
11767
11768 if (mPendingBroadcast == r) {
11769 mPendingBroadcast = null;
11770 }
11771
11772 // Move on to the next receiver.
11773 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
11774 r.resultExtras, r.resultAbort, true);
11775 scheduleBroadcastsLocked();
11776
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011777 if (anrMessage != null) {
Jeff Brown4d94a762010-09-23 11:33:28 -070011778 // Post the ANR to the handler since we do not want to process ANRs while
11779 // potentially holding our lock.
11780 mHandler.post(new AppNotResponding(app, anrMessage));
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011781 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011782 }
11783
11784 private final void processCurBroadcastLocked(BroadcastRecord r,
11785 ProcessRecord app) throws RemoteException {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011786 if (DEBUG_BROADCAST) Slog.v(TAG,
11787 "Process cur broadcast " + r + " for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011788 if (app.thread == null) {
11789 throw new RemoteException();
11790 }
11791 r.receiver = app.thread.asBinder();
11792 r.curApp = app;
11793 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011794 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011795
11796 // Tell the application to launch this receiver.
11797 r.intent.setComponent(r.curComponent);
11798
11799 boolean started = false;
11800 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011801 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011802 "Delivering to component " + r.curComponent
11803 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070011804 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011805 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
Dianne Hackborne2515ee2011-04-27 18:52:56 -040011806 compatibilityInfoForPackageLocked(r.curReceiver.applicationInfo),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011807 r.resultCode, r.resultData, r.resultExtras, r.ordered);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011808 if (DEBUG_BROADCAST) Slog.v(TAG,
11809 "Process cur broadcast " + r + " DELIVERED for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011810 started = true;
11811 } finally {
11812 if (!started) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011813 if (DEBUG_BROADCAST) Slog.v(TAG,
11814 "Process cur broadcast " + r + ": NOT STARTED!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011815 r.receiver = null;
11816 r.curApp = null;
11817 app.curReceiver = null;
11818 }
11819 }
11820
11821 }
11822
Jeff Brown4d94a762010-09-23 11:33:28 -070011823 static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011824 Intent intent, int resultCode, String data, Bundle extras,
11825 boolean ordered, boolean sticky) throws RemoteException {
Jeff Brown4d94a762010-09-23 11:33:28 -070011826 // Send the intent to the receiver asynchronously using one-way binder calls.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011827 if (app != null && app.thread != null) {
11828 // If we have an app thread, do the call through that so it is
11829 // correctly ordered with other one-way calls.
11830 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011831 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011832 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011833 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011834 }
11835 }
11836
Jeff Brown4d94a762010-09-23 11:33:28 -070011837 private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011838 BroadcastFilter filter, boolean ordered) {
11839 boolean skip = false;
11840 if (filter.requiredPermission != null) {
11841 int perm = checkComponentPermission(filter.requiredPermission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011842 r.callingPid, r.callingUid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011843 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011844 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011845 + r.intent.toString()
11846 + " from " + r.callerPackage + " (pid="
11847 + r.callingPid + ", uid=" + r.callingUid + ")"
11848 + " requires " + filter.requiredPermission
11849 + " due to registered receiver " + filter);
11850 skip = true;
11851 }
11852 }
11853 if (r.requiredPermission != null) {
11854 int perm = checkComponentPermission(r.requiredPermission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011855 filter.receiverList.pid, filter.receiverList.uid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011856 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011857 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011858 + r.intent.toString()
11859 + " to " + filter.receiverList.app
11860 + " (pid=" + filter.receiverList.pid
11861 + ", uid=" + filter.receiverList.uid + ")"
11862 + " requires " + r.requiredPermission
11863 + " due to sender " + r.callerPackage
11864 + " (uid " + r.callingUid + ")");
11865 skip = true;
11866 }
11867 }
11868
11869 if (!skip) {
11870 // If this is not being sent as an ordered broadcast, then we
11871 // don't want to touch the fields that keep track of the current
11872 // state of ordered broadcasts.
11873 if (ordered) {
11874 r.receiver = filter.receiverList.receiver.asBinder();
11875 r.curFilter = filter;
11876 filter.receiverList.curBroadcast = r;
11877 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011878 if (filter.receiverList.app != null) {
11879 // Bump hosting application to no longer be in background
11880 // scheduling class. Note that we can't do that if there
11881 // isn't an app... but we can only be in that case for
11882 // things that directly call the IActivityManager API, which
11883 // are already core system stuff so don't matter for this.
11884 r.curApp = filter.receiverList.app;
11885 filter.receiverList.app.curReceiver = r;
11886 updateOomAdjLocked();
11887 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011888 }
11889 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011890 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011891 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011892 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011893 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011894 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011895 performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011896 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011897 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011898 if (ordered) {
11899 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
11900 }
11901 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011902 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011903 if (ordered) {
11904 r.receiver = null;
11905 r.curFilter = null;
11906 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011907 if (filter.receiverList.app != null) {
11908 filter.receiverList.app.curReceiver = null;
11909 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011910 }
11911 }
11912 }
11913 }
11914
Dianne Hackborn12527f92009-11-11 17:39:50 -080011915 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
11916 if (r.callingUid < 0) {
11917 // This was from a registerReceiver() call; ignore it.
11918 return;
11919 }
11920 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
11921 MAX_BROADCAST_HISTORY-1);
11922 r.finishTime = SystemClock.uptimeMillis();
11923 mBroadcastHistory[0] = r;
11924 }
11925
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011926 private final void processNextBroadcast(boolean fromMsg) {
11927 synchronized(this) {
11928 BroadcastRecord r;
11929
Joe Onorato8a9b2202010-02-26 18:56:32 -080011930 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011931 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011932 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011933
11934 updateCpuStats();
11935
11936 if (fromMsg) {
11937 mBroadcastsScheduled = false;
11938 }
11939
11940 // First, deliver any non-serialized broadcasts right away.
11941 while (mParallelBroadcasts.size() > 0) {
11942 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080011943 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011944 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011945 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011946 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011947 for (int i=0; i<N; i++) {
11948 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011949 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011950 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011951 + target + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011952 deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011953 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080011954 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011955 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011956 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011957 }
11958
11959 // Now take care of the next serialized one...
11960
11961 // If we are waiting for a process to come up to handle the next
11962 // broadcast, then do nothing at this point. Just in case, we
11963 // check that the process we're waiting for still exists.
11964 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070011965 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011966 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070011967 + mPendingBroadcast.curApp);
11968 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011969
11970 boolean isDead;
11971 synchronized (mPidsSelfLocked) {
11972 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
11973 }
11974 if (!isDead) {
11975 // It's still alive, so keep waiting
11976 return;
11977 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011978 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011979 + " died before responding to broadcast");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011980 mPendingBroadcast.state = BroadcastRecord.IDLE;
11981 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011982 mPendingBroadcast = null;
11983 }
11984 }
11985
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011986 boolean looped = false;
11987
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011988 do {
11989 if (mOrderedBroadcasts.size() == 0) {
11990 // No more broadcasts pending, so all done!
11991 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011992 if (looped) {
11993 // If we had finished the last ordered broadcast, then
11994 // make sure all processes have correct oom and sched
11995 // adjustments.
11996 updateOomAdjLocked();
11997 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011998 return;
11999 }
12000 r = mOrderedBroadcasts.get(0);
12001 boolean forceReceive = false;
12002
12003 // Ensure that even if something goes awry with the timeout
12004 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050012005 // and continue to make progress.
12006 //
12007 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
Jeff Brown4d94a762010-09-23 11:33:28 -070012008 // receivers don't get executed with timeouts. They're intended for
Jeff Hamiltonacf84742010-05-25 22:10:18 -050012009 // one time heavy lifting after system upgrades and can take
12010 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012011 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012012 if (mProcessesReady && r.dispatchTime > 0) {
Jeff Hamiltonacf84742010-05-25 22:10:18 -050012013 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012014 if ((numReceivers > 0) &&
12015 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012016 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012017 + " now=" + now
12018 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080012019 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012020 + " intent=" + r.intent
12021 + " numReceivers=" + numReceivers
12022 + " nextReceiver=" + r.nextReceiver
12023 + " state=" + r.state);
Jeff Brown4d94a762010-09-23 11:33:28 -070012024 broadcastTimeoutLocked(false); // forcibly finish this broadcast
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012025 forceReceive = true;
12026 r.state = BroadcastRecord.IDLE;
12027 }
12028 }
12029
12030 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012031 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012032 "processNextBroadcast() called when not idle (state="
12033 + r.state + ")");
12034 return;
12035 }
12036
12037 if (r.receivers == null || r.nextReceiver >= numReceivers
12038 || r.resultAbort || forceReceive) {
12039 // No more receivers for this broadcast! Send the final
12040 // result if requested...
12041 if (r.resultTo != null) {
12042 try {
12043 if (DEBUG_BROADCAST) {
12044 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012045 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012046 + " seq=" + seq + " app=" + r.callerApp);
12047 }
Jeff Brown4d94a762010-09-23 11:33:28 -070012048 performReceiveLocked(r.callerApp, r.resultTo,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012049 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012050 r.resultData, r.resultExtras, false, false);
Johannes Carlssonb5a86542010-10-27 10:08:10 +020012051 // Set this to null so that the reference
12052 // (local and remote) isnt kept in the mBroadcastHistory.
12053 r.resultTo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012054 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012055 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012056 }
12057 }
12058
Joe Onorato8a9b2202010-02-26 18:56:32 -080012059 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
Jeff Brown4d94a762010-09-23 11:33:28 -070012060 cancelBroadcastTimeoutLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012061
Joe Onorato8a9b2202010-02-26 18:56:32 -080012062 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012063 + r);
12064
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012065 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080012066 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012067 mOrderedBroadcasts.remove(0);
12068 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012069 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012070 continue;
12071 }
12072 } while (r == null);
12073
12074 // Get the next receiver...
12075 int recIdx = r.nextReceiver++;
12076
12077 // Keep track of when this receiver started, and make sure there
12078 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080012079 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012080 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080012081 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012082
Joe Onorato8a9b2202010-02-26 18:56:32 -080012083 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012084 + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070012085 }
12086 if (! mPendingBroadcastTimeoutMessage) {
12087 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012088 if (DEBUG_BROADCAST) Slog.v(TAG,
Jeff Brown4d94a762010-09-23 11:33:28 -070012089 "Submitting BROADCAST_TIMEOUT_MSG for " + r + " at " + timeoutTime);
12090 setBroadcastTimeoutLocked(timeoutTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012091 }
12092
12093 Object nextReceiver = r.receivers.get(recIdx);
12094 if (nextReceiver instanceof BroadcastFilter) {
12095 // Simple case: this is a registered receiver who gets
12096 // a direct call.
12097 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012098 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070012099 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012100 + filter + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070012101 deliverToRegisteredReceiverLocked(r, filter, r.ordered);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012102 if (r.receiver == null || !r.ordered) {
12103 // The receiver has already finished, so schedule to
12104 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070012105 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
12106 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012107 r.state = BroadcastRecord.IDLE;
12108 scheduleBroadcastsLocked();
12109 }
12110 return;
12111 }
12112
12113 // Hard case: need to instantiate the receiver, possibly
12114 // starting its application process to host it.
12115
12116 ResolveInfo info =
12117 (ResolveInfo)nextReceiver;
12118
12119 boolean skip = false;
12120 int perm = checkComponentPermission(info.activityInfo.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080012121 r.callingPid, r.callingUid, info.activityInfo.applicationInfo.uid,
12122 info.activityInfo.exported);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012123 if (perm != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080012124 if (!info.activityInfo.exported) {
12125 Slog.w(TAG, "Permission Denial: broadcasting "
12126 + r.intent.toString()
12127 + " from " + r.callerPackage + " (pid=" + r.callingPid
12128 + ", uid=" + r.callingUid + ")"
12129 + " is not exported from uid " + info.activityInfo.applicationInfo.uid
12130 + " due to receiver " + info.activityInfo.packageName
12131 + "/" + info.activityInfo.name);
12132 } else {
12133 Slog.w(TAG, "Permission Denial: broadcasting "
12134 + r.intent.toString()
12135 + " from " + r.callerPackage + " (pid=" + r.callingPid
12136 + ", uid=" + r.callingUid + ")"
12137 + " requires " + info.activityInfo.permission
12138 + " due to receiver " + info.activityInfo.packageName
12139 + "/" + info.activityInfo.name);
12140 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012141 skip = true;
12142 }
12143 if (r.callingUid != Process.SYSTEM_UID &&
12144 r.requiredPermission != null) {
12145 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012146 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012147 checkPermission(r.requiredPermission,
12148 info.activityInfo.applicationInfo.packageName);
12149 } catch (RemoteException e) {
12150 perm = PackageManager.PERMISSION_DENIED;
12151 }
12152 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012153 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012154 + r.intent + " to "
12155 + info.activityInfo.applicationInfo.packageName
12156 + " requires " + r.requiredPermission
12157 + " due to sender " + r.callerPackage
12158 + " (uid " + r.callingUid + ")");
12159 skip = true;
12160 }
12161 }
12162 if (r.curApp != null && r.curApp.crashing) {
12163 // If the target process is crashing, just skip it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012164 if (DEBUG_BROADCAST) Slog.v(TAG,
12165 "Skipping deliver ordered " + r + " to " + r.curApp
12166 + ": process crashing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012167 skip = true;
12168 }
12169
12170 if (skip) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012171 if (DEBUG_BROADCAST) Slog.v(TAG,
12172 "Skipping delivery of ordered " + r + " for whatever reason");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012173 r.receiver = null;
12174 r.curFilter = null;
12175 r.state = BroadcastRecord.IDLE;
12176 scheduleBroadcastsLocked();
12177 return;
12178 }
12179
12180 r.state = BroadcastRecord.APP_RECEIVE;
12181 String targetProcess = info.activityInfo.processName;
12182 r.curComponent = new ComponentName(
12183 info.activityInfo.applicationInfo.packageName,
12184 info.activityInfo.name);
12185 r.curReceiver = info.activityInfo;
12186
Dianne Hackborne7f97212011-02-24 14:40:20 -080012187 // Broadcast is being executed, its package can't be stopped.
12188 try {
12189 AppGlobals.getPackageManager().setPackageStoppedState(
12190 r.curComponent.getPackageName(), false);
12191 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -080012192 } catch (IllegalArgumentException e) {
12193 Slog.w(TAG, "Failed trying to unstop package "
12194 + r.curComponent.getPackageName() + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -080012195 }
12196
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012197 // Is this receiver's application already running?
12198 ProcessRecord app = getProcessRecordLocked(targetProcess,
12199 info.activityInfo.applicationInfo.uid);
12200 if (app != null && app.thread != null) {
12201 try {
Dianne Hackborn6c418d52011-06-29 14:05:33 -070012202 app.addPackage(info.activityInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012203 processCurBroadcastLocked(r, app);
12204 return;
12205 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012206 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012207 + r.curComponent, e);
12208 }
12209
12210 // If a dead object exception was thrown -- fall through to
12211 // restart the application.
12212 }
12213
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012214 // Not running -- get it started, to be executed when the app comes up.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012215 if (DEBUG_BROADCAST) Slog.v(TAG,
12216 "Need to start app " + targetProcess + " for broadcast " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012217 if ((r.curApp=startProcessLocked(targetProcess,
12218 info.activityInfo.applicationInfo, true,
12219 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012220 "broadcast", r.curComponent,
12221 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
12222 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012223 // Ah, this recipient is unavailable. Finish it if necessary,
12224 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012225 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012226 + info.activityInfo.applicationInfo.packageName + "/"
12227 + info.activityInfo.applicationInfo.uid + " for broadcast "
12228 + r.intent + ": process is bad");
Jeff Brown4d94a762010-09-23 11:33:28 -070012229 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012230 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
12231 r.resultExtras, r.resultAbort, true);
12232 scheduleBroadcastsLocked();
12233 r.state = BroadcastRecord.IDLE;
12234 return;
12235 }
12236
12237 mPendingBroadcast = r;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012238 mPendingBroadcastRecvIndex = recIdx;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012239 }
12240 }
12241
12242 // =========================================================
12243 // INSTRUMENTATION
12244 // =========================================================
12245
12246 public boolean startInstrumentation(ComponentName className,
12247 String profileFile, int flags, Bundle arguments,
12248 IInstrumentationWatcher watcher) {
12249 // Refuse possible leaked file descriptors
12250 if (arguments != null && arguments.hasFileDescriptors()) {
12251 throw new IllegalArgumentException("File descriptors passed in Bundle");
12252 }
12253
12254 synchronized(this) {
12255 InstrumentationInfo ii = null;
12256 ApplicationInfo ai = null;
12257 try {
12258 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012259 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012260 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012261 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012262 } catch (PackageManager.NameNotFoundException e) {
12263 }
12264 if (ii == null) {
12265 reportStartInstrumentationFailure(watcher, className,
12266 "Unable to find instrumentation info for: " + className);
12267 return false;
12268 }
12269 if (ai == null) {
12270 reportStartInstrumentationFailure(watcher, className,
12271 "Unable to find instrumentation target package: " + ii.targetPackage);
12272 return false;
12273 }
12274
12275 int match = mContext.getPackageManager().checkSignatures(
12276 ii.targetPackage, ii.packageName);
12277 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
12278 String msg = "Permission Denial: starting instrumentation "
12279 + className + " from pid="
12280 + Binder.getCallingPid()
12281 + ", uid=" + Binder.getCallingPid()
12282 + " not allowed because package " + ii.packageName
12283 + " does not have a signature matching the target "
12284 + ii.targetPackage;
12285 reportStartInstrumentationFailure(watcher, className, msg);
12286 throw new SecurityException(msg);
12287 }
12288
12289 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012290 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012291 ProcessRecord app = addAppLocked(ai);
12292 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070012293 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012294 app.instrumentationProfileFile = profileFile;
12295 app.instrumentationArguments = arguments;
12296 app.instrumentationWatcher = watcher;
12297 app.instrumentationResultClass = className;
12298 Binder.restoreCallingIdentity(origId);
12299 }
12300
12301 return true;
12302 }
12303
12304 /**
12305 * Report errors that occur while attempting to start Instrumentation. Always writes the
12306 * error to the logs, but if somebody is watching, send the report there too. This enables
12307 * the "am" command to report errors with more information.
12308 *
12309 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
12310 * @param cn The component name of the instrumentation.
12311 * @param report The error report.
12312 */
12313 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
12314 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012315 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012316 try {
12317 if (watcher != null) {
12318 Bundle results = new Bundle();
12319 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
12320 results.putString("Error", report);
12321 watcher.instrumentationStatus(cn, -1, results);
12322 }
12323 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012324 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012325 }
12326 }
12327
12328 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
12329 if (app.instrumentationWatcher != null) {
12330 try {
12331 // NOTE: IInstrumentationWatcher *must* be oneway here
12332 app.instrumentationWatcher.instrumentationFinished(
12333 app.instrumentationClass,
12334 resultCode,
12335 results);
12336 } catch (RemoteException e) {
12337 }
12338 }
12339 app.instrumentationWatcher = null;
12340 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070012341 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012342 app.instrumentationProfileFile = null;
12343 app.instrumentationArguments = null;
12344
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012345 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012346 }
12347
12348 public void finishInstrumentation(IApplicationThread target,
12349 int resultCode, Bundle results) {
12350 // Refuse possible leaked file descriptors
12351 if (results != null && results.hasFileDescriptors()) {
12352 throw new IllegalArgumentException("File descriptors passed in Intent");
12353 }
12354
12355 synchronized(this) {
12356 ProcessRecord app = getRecordForAppLocked(target);
12357 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012358 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012359 return;
12360 }
12361 final long origId = Binder.clearCallingIdentity();
12362 finishInstrumentationLocked(app, resultCode, results);
12363 Binder.restoreCallingIdentity(origId);
12364 }
12365 }
12366
12367 // =========================================================
12368 // CONFIGURATION
12369 // =========================================================
12370
12371 public ConfigurationInfo getDeviceConfigurationInfo() {
12372 ConfigurationInfo config = new ConfigurationInfo();
12373 synchronized (this) {
12374 config.reqTouchScreen = mConfiguration.touchscreen;
12375 config.reqKeyboardType = mConfiguration.keyboard;
12376 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070012377 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
12378 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012379 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
12380 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070012381 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
12382 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012383 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
12384 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070012385 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012386 }
12387 return config;
12388 }
12389
12390 public Configuration getConfiguration() {
12391 Configuration ci;
12392 synchronized(this) {
12393 ci = new Configuration(mConfiguration);
12394 }
12395 return ci;
12396 }
12397
12398 public void updateConfiguration(Configuration values) {
12399 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
12400 "updateConfiguration()");
12401
12402 synchronized(this) {
12403 if (values == null && mWindowManager != null) {
12404 // sentinel: fetch the current configuration from the window manager
12405 values = mWindowManager.computeNewConfiguration();
12406 }
12407
12408 final long origId = Binder.clearCallingIdentity();
12409 updateConfigurationLocked(values, null);
12410 Binder.restoreCallingIdentity(origId);
12411 }
12412 }
12413
12414 /**
12415 * Do either or both things: (1) change the current configuration, and (2)
12416 * make sure the given activity is running with the (now) current
12417 * configuration. Returns true if the activity has been left running, or
12418 * false if <var>starting</var> is being destroyed to match the new
12419 * configuration.
12420 */
12421 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012422 ActivityRecord starting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012423 int changes = 0;
12424
12425 boolean kept = true;
12426
12427 if (values != null) {
12428 Configuration newConfig = new Configuration(mConfiguration);
12429 changes = newConfig.updateFrom(values);
12430 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070012431 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012432 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012433 }
12434
Doug Zongker2bec3d42009-12-04 12:52:44 -080012435 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012436
12437 if (values.locale != null) {
12438 saveLocaleLocked(values.locale,
12439 !values.locale.equals(mConfiguration.locale),
12440 values.userSetLocale);
12441 }
12442
Dianne Hackborne36d6e22010-02-17 19:46:25 -080012443 mConfigurationSeq++;
12444 if (mConfigurationSeq <= 0) {
12445 mConfigurationSeq = 1;
12446 }
12447 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012448 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012449 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080012450
12451 AttributeCache ac = AttributeCache.instance();
12452 if (ac != null) {
12453 ac.updateConfiguration(mConfiguration);
12454 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012455
Dianne Hackborn2f0b1752011-05-31 17:59:49 -070012456 // Make sure all resources in our process are updated
12457 // right now, so that anyone who is going to retrieve
12458 // resource values after we return will be sure to get
12459 // the new ones. This is especially important during
12460 // boot, where the first config change needs to guarantee
12461 // all resources have that config before following boot
12462 // code is executed.
12463 mSystemThread.applyConfigurationToResources(newConfig);
12464
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080012465 if (Settings.System.hasInterestingConfigurationChanges(changes)) {
12466 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
12467 msg.obj = new Configuration(mConfiguration);
12468 mHandler.sendMessage(msg);
12469 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012470
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012471 for (int i=mLruProcesses.size()-1; i>=0; i--) {
12472 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012473 try {
12474 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012475 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070012476 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012477 app.thread.scheduleConfigurationChanged(mConfiguration);
12478 }
12479 } catch (Exception e) {
12480 }
12481 }
12482 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012483 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
12484 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012485 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
12486 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080012487 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
12488 broadcastIntentLocked(null, null,
12489 new Intent(Intent.ACTION_LOCALE_CHANGED),
12490 null, null, 0, null, null,
12491 null, false, false, MY_PID, Process.SYSTEM_UID);
12492 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012493 }
12494 }
12495
12496 if (changes != 0 && starting == null) {
12497 // If the configuration changed, and the caller is not already
12498 // in the process of starting an activity, then find the top
12499 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012500 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012501 }
12502
12503 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012504 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
Dianne Hackborn5f4d6432010-12-21 20:40:11 -080012505 // And we need to make sure at this point that all other activities
12506 // are made visible with the correct configuration.
12507 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012508 }
12509
Dianne Hackborne36d6e22010-02-17 19:46:25 -080012510 if (values != null && mWindowManager != null) {
12511 mWindowManager.setNewConfiguration(mConfiguration);
12512 }
12513
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012514 return kept;
12515 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012516
12517 /**
12518 * Save the locale. You must be inside a synchronized (this) block.
12519 */
12520 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
12521 if(isDiff) {
12522 SystemProperties.set("user.language", l.getLanguage());
12523 SystemProperties.set("user.region", l.getCountry());
12524 }
12525
12526 if(isPersist) {
12527 SystemProperties.set("persist.sys.language", l.getLanguage());
12528 SystemProperties.set("persist.sys.country", l.getCountry());
12529 SystemProperties.set("persist.sys.localevar", l.getVariant());
12530 }
12531 }
12532
12533 // =========================================================
12534 // LIFETIME MANAGEMENT
12535 // =========================================================
12536
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012537 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
12538 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012539 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012540 // This adjustment has already been computed. If we are calling
12541 // from the top, we may have already computed our adjustment with
12542 // an earlier hidden adjustment that isn't really for us... if
12543 // so, use the new hidden adjustment.
12544 if (!recursed && app.hidden) {
12545 app.curAdj = hiddenAdj;
12546 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012547 return app.curAdj;
12548 }
12549
12550 if (app.thread == null) {
12551 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012552 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012553 return (app.curAdj=EMPTY_APP_ADJ);
12554 }
12555
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012556 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
12557 // The max adjustment doesn't allow this app to be anything
12558 // below foreground, so it is not worth doing work for it.
12559 app.adjType = "fixed";
12560 app.adjSeq = mAdjSeq;
12561 app.curRawAdj = app.maxAdj;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012562 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012563 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
12564 return (app.curAdj=app.maxAdj);
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012565 }
12566
12567 final boolean hadForegroundActivities = app.foregroundActivities;
12568
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012569 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012570 app.adjSource = null;
12571 app.adjTarget = null;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012572 app.keeping = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012573 app.empty = false;
12574 app.hidden = false;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012575 app.foregroundActivities = false;
12576
12577 final int activitiesSize = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012578
The Android Open Source Project4df24232009-03-05 14:34:35 -080012579 // Determine the importance of the process, starting with most
12580 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012581 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012582 int schedGroup;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012583 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012584 // The last app on the list is the foreground app.
12585 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012586 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012587 app.adjType = "top-activity";
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012588 app.foregroundActivities = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012589 } else if (app.instrumentationClass != null) {
12590 // Don't want to kill running instrumentation.
12591 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012592 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012593 app.adjType = "instrumentation";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012594 } else if (app.curReceiver != null ||
12595 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
12596 // An app that is currently receiving a broadcast also
12597 // counts as being in the foreground.
12598 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012599 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012600 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012601 } else if (app.executingServices.size() > 0) {
12602 // An app that is currently executing a service callback also
12603 // counts as being in the foreground.
12604 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012605 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012606 app.adjType = "exec-service";
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012607 } else if (activitiesSize > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012608 // This app is in the background with paused activities.
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012609 // We inspect activities to potentially upgrade adjustment further below.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012610 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012611 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012612 app.hidden = true;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012613 app.adjType = "bg-activities";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012614 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012615 // A very not-needed process. If this is lower in the lru list,
12616 // we will push it in to the empty bucket.
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012617 adj = hiddenAdj;
12618 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012619 app.hidden = true;
12620 app.empty = true;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012621 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012622 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012623
12624 // Examine all activities if not already foreground.
12625 if (!app.foregroundActivities && activitiesSize > 0) {
12626 for (int j = 0; j < activitiesSize; j++) {
12627 final ActivityRecord r = app.activities.get(j);
12628 if (r.visible) {
12629 // App has a visible activity; only upgrade adjustment.
12630 if (adj > VISIBLE_APP_ADJ) {
12631 adj = VISIBLE_APP_ADJ;
12632 app.adjType = "visible";
12633 }
12634 schedGroup = Process.THREAD_GROUP_DEFAULT;
12635 app.hidden = false;
12636 app.foregroundActivities = true;
12637 break;
12638 } else if (r.state == ActivityState.PAUSING || r.state == ActivityState.PAUSED
12639 || r.state == ActivityState.STOPPING) {
12640 // Only upgrade adjustment.
12641 if (adj > PERCEPTIBLE_APP_ADJ) {
12642 adj = PERCEPTIBLE_APP_ADJ;
12643 app.adjType = "stopping";
12644 }
12645 app.foregroundActivities = true;
12646 }
12647 }
12648 }
12649
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012650 if (adj > PERCEPTIBLE_APP_ADJ) {
12651 if (app.foregroundServices) {
12652 // The user is aware of this app, so make it visible.
12653 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012654 app.adjType = "foreground-service";
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012655 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012656 } else if (app.forcingToForeground != null) {
12657 // The user is aware of this app, so make it visible.
12658 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012659 app.adjType = "force-foreground";
12660 app.adjSource = app.forcingToForeground;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012661 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012662 }
12663 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012664
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012665 if (adj > HEAVY_WEIGHT_APP_ADJ && app == mHeavyWeightProcess) {
12666 // We don't want to kill the current heavy-weight process.
12667 adj = HEAVY_WEIGHT_APP_ADJ;
12668 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
12669 app.adjType = "heavy";
12670 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012671
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012672 if (adj > HOME_APP_ADJ && app == mHomeProcess) {
12673 // This process is hosting what we currently consider to be the
12674 // home app, so we don't want to let it go into the background.
12675 adj = HOME_APP_ADJ;
12676 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
12677 app.adjType = "home";
12678 }
12679
Joe Onorato8a9b2202010-02-26 18:56:32 -080012680 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012681
The Android Open Source Project4df24232009-03-05 14:34:35 -080012682 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012683 // there are applications dependent on our services or providers, but
12684 // this gives us a baseline and makes sure we don't get into an
12685 // infinite recursion.
12686 app.adjSeq = mAdjSeq;
12687 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012688
Christopher Tate6fa95972009-06-05 18:43:55 -070012689 if (mBackupTarget != null && app == mBackupTarget.app) {
12690 // If possible we want to avoid killing apps while they're being backed up
12691 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012692 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070012693 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012694 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012695 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070012696 }
12697 }
12698
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012699 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
12700 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012701 final long now = SystemClock.uptimeMillis();
12702 // This process is more important if the top activity is
12703 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070012704 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012705 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012706 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012707 if (s.startRequested) {
12708 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
12709 // This service has seen some activity within
12710 // recent memory, so we will keep its process ahead
12711 // of the background processes.
12712 if (adj > SECONDARY_SERVER_ADJ) {
12713 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012714 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012715 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012716 }
12717 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012718 // If we have let the service slide into the background
12719 // state, still have some text describing what it is doing
12720 // even though the service no longer has an impact.
12721 if (adj > SECONDARY_SERVER_ADJ) {
12722 app.adjType = "started-bg-services";
12723 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012724 // Don't kill this process because it is doing work; it
12725 // has said it is doing work.
12726 app.keeping = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012727 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012728 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
12729 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012730 Iterator<ArrayList<ConnectionRecord>> kt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012731 = s.connections.values().iterator();
12732 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012733 ArrayList<ConnectionRecord> clist = kt.next();
12734 for (int i=0; i<clist.size() && adj > FOREGROUND_APP_ADJ; i++) {
12735 // XXX should compute this based on the max of
12736 // all connected clients.
12737 ConnectionRecord cr = clist.get(i);
12738 if (cr.binding.client == app) {
12739 // Binding to ourself is not interesting.
12740 continue;
12741 }
12742 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
12743 ProcessRecord client = cr.binding.client;
12744 int myHiddenAdj = hiddenAdj;
12745 if (myHiddenAdj > client.hiddenAdj) {
12746 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
12747 myHiddenAdj = client.hiddenAdj;
12748 } else {
12749 myHiddenAdj = VISIBLE_APP_ADJ;
12750 }
12751 }
12752 int clientAdj = computeOomAdjLocked(
12753 client, myHiddenAdj, TOP_APP, true);
12754 if (adj > clientAdj) {
12755 adj = clientAdj >= VISIBLE_APP_ADJ
12756 ? clientAdj : VISIBLE_APP_ADJ;
12757 if (!client.hidden) {
12758 app.hidden = false;
12759 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012760 if (client.keeping) {
12761 app.keeping = true;
12762 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012763 app.adjType = "service";
12764 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12765 .REASON_SERVICE_IN_USE;
12766 app.adjSource = cr.binding.client;
12767 app.adjTarget = s.name;
12768 }
12769 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
12770 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
12771 schedGroup = Process.THREAD_GROUP_DEFAULT;
12772 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012773 }
12774 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012775 ActivityRecord a = cr.activity;
12776 //if (a != null) {
12777 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
12778 //}
12779 if (a != null && adj > FOREGROUND_APP_ADJ &&
12780 (a.state == ActivityState.RESUMED
12781 || a.state == ActivityState.PAUSING)) {
12782 adj = FOREGROUND_APP_ADJ;
12783 schedGroup = Process.THREAD_GROUP_DEFAULT;
12784 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012785 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012786 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12787 .REASON_SERVICE_IN_USE;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012788 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012789 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012790 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012791 }
12792 }
12793 }
12794 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012795
Dianne Hackborn287952c2010-09-22 22:34:31 -070012796 // Finally, if this process has active services running in it, we
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012797 // would like to avoid killing it unless it would prevent the current
12798 // application from running. By default we put the process in
12799 // with the rest of the background processes; as we scan through
12800 // its services we may bump it up from there.
12801 if (adj > hiddenAdj) {
12802 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012803 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012804 app.adjType = "bg-services";
12805 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012806 }
12807
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012808 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
12809 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012810 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012811 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
12812 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012813 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012814 if (cpr.clients.size() != 0) {
12815 Iterator<ProcessRecord> kt = cpr.clients.iterator();
12816 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
12817 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070012818 if (client == app) {
12819 // Being our own client is not interesting.
12820 continue;
12821 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012822 int myHiddenAdj = hiddenAdj;
12823 if (myHiddenAdj > client.hiddenAdj) {
12824 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
12825 myHiddenAdj = client.hiddenAdj;
12826 } else {
12827 myHiddenAdj = FOREGROUND_APP_ADJ;
12828 }
12829 }
12830 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012831 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012832 if (adj > clientAdj) {
12833 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012834 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012835 if (!client.hidden) {
12836 app.hidden = false;
12837 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012838 if (client.keeping) {
12839 app.keeping = true;
12840 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012841 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012842 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12843 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012844 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012845 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012846 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012847 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
12848 schedGroup = Process.THREAD_GROUP_DEFAULT;
12849 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012850 }
12851 }
12852 // If the provider has external (non-framework) process
12853 // dependencies, ensure that its adjustment is at least
12854 // FOREGROUND_APP_ADJ.
12855 if (cpr.externals != 0) {
12856 if (adj > FOREGROUND_APP_ADJ) {
12857 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012858 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012859 app.hidden = false;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012860 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012861 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012862 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012863 }
12864 }
12865 }
12866 }
12867
12868 app.curRawAdj = adj;
12869
Joe Onorato8a9b2202010-02-26 18:56:32 -080012870 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012871 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
12872 if (adj > app.maxAdj) {
12873 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070012874 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012875 schedGroup = Process.THREAD_GROUP_DEFAULT;
12876 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012877 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012878 if (adj < HIDDEN_APP_MIN_ADJ) {
12879 app.keeping = true;
12880 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012881
12882 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012883 app.curSchedGroup = schedGroup;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012884
12885 if (hadForegroundActivities != app.foregroundActivities) {
Jeff Sharkey287bd832011-05-28 19:36:26 -070012886 mHandler.obtainMessage(DISPATCH_FOREGROUND_ACTIVITIES_CHANGED, app.pid, app.info.uid,
12887 app.foregroundActivities).sendToTarget();
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012888 }
12889
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012890 return adj;
12891 }
12892
12893 /**
12894 * Ask a given process to GC right now.
12895 */
12896 final void performAppGcLocked(ProcessRecord app) {
12897 try {
12898 app.lastRequestedGc = SystemClock.uptimeMillis();
12899 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012900 if (app.reportLowMemory) {
12901 app.reportLowMemory = false;
12902 app.thread.scheduleLowMemory();
12903 } else {
12904 app.thread.processInBackground();
12905 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012906 }
12907 } catch (Exception e) {
12908 // whatever.
12909 }
12910 }
12911
12912 /**
12913 * Returns true if things are idle enough to perform GCs.
12914 */
Josh Bartel7f208742010-02-25 11:01:44 -060012915 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012916 return mParallelBroadcasts.size() == 0
12917 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012918 && (mSleeping || (mMainStack.mResumedActivity != null &&
12919 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012920 }
12921
12922 /**
12923 * Perform GCs on all processes that are waiting for it, but only
12924 * if things are idle.
12925 */
12926 final void performAppGcsLocked() {
12927 final int N = mProcessesToGc.size();
12928 if (N <= 0) {
12929 return;
12930 }
Josh Bartel7f208742010-02-25 11:01:44 -060012931 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012932 while (mProcessesToGc.size() > 0) {
12933 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070012934 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012935 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
12936 <= SystemClock.uptimeMillis()) {
12937 // To avoid spamming the system, we will GC processes one
12938 // at a time, waiting a few seconds between each.
12939 performAppGcLocked(proc);
12940 scheduleAppGcsLocked();
12941 return;
12942 } else {
12943 // It hasn't been long enough since we last GCed this
12944 // process... put it in the list to wait for its time.
12945 addProcessToGcListLocked(proc);
12946 break;
12947 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012948 }
12949 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012950
12951 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012952 }
12953 }
12954
12955 /**
12956 * If all looks good, perform GCs on all processes waiting for them.
12957 */
12958 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060012959 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012960 performAppGcsLocked();
12961 return;
12962 }
12963 // Still not idle, wait some more.
12964 scheduleAppGcsLocked();
12965 }
12966
12967 /**
12968 * Schedule the execution of all pending app GCs.
12969 */
12970 final void scheduleAppGcsLocked() {
12971 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012972
12973 if (mProcessesToGc.size() > 0) {
12974 // Schedule a GC for the time to the next process.
12975 ProcessRecord proc = mProcessesToGc.get(0);
12976 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
12977
Dianne Hackbornce86ba82011-07-13 19:33:41 -070012978 long when = proc.lastRequestedGc + GC_MIN_INTERVAL;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012979 long now = SystemClock.uptimeMillis();
12980 if (when < (now+GC_TIMEOUT)) {
12981 when = now + GC_TIMEOUT;
12982 }
12983 mHandler.sendMessageAtTime(msg, when);
12984 }
12985 }
12986
12987 /**
12988 * Add a process to the array of processes waiting to be GCed. Keeps the
12989 * list in sorted order by the last GC time. The process can't already be
12990 * on the list.
12991 */
12992 final void addProcessToGcListLocked(ProcessRecord proc) {
12993 boolean added = false;
12994 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
12995 if (mProcessesToGc.get(i).lastRequestedGc <
12996 proc.lastRequestedGc) {
12997 added = true;
12998 mProcessesToGc.add(i+1, proc);
12999 break;
13000 }
13001 }
13002 if (!added) {
13003 mProcessesToGc.add(0, proc);
13004 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013005 }
13006
13007 /**
13008 * Set up to ask a process to GC itself. This will either do it
13009 * immediately, or put it on the list of processes to gc the next
13010 * time things are idle.
13011 */
13012 final void scheduleAppGcLocked(ProcessRecord app) {
13013 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013014 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013015 return;
13016 }
13017 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013018 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013019 scheduleAppGcsLocked();
13020 }
13021 }
13022
Dianne Hackborn287952c2010-09-22 22:34:31 -070013023 final void checkExcessivePowerUsageLocked(boolean doKills) {
13024 updateCpuStatsNow();
13025
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013026 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
Dianne Hackborn287952c2010-09-22 22:34:31 -070013027 boolean doWakeKills = doKills;
13028 boolean doCpuKills = doKills;
13029 if (mLastPowerCheckRealtime == 0) {
13030 doWakeKills = false;
13031 }
13032 if (mLastPowerCheckUptime == 0) {
13033 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013034 }
13035 if (stats.isScreenOn()) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070013036 doWakeKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013037 }
13038 final long curRealtime = SystemClock.elapsedRealtime();
Dianne Hackborn287952c2010-09-22 22:34:31 -070013039 final long realtimeSince = curRealtime - mLastPowerCheckRealtime;
13040 final long curUptime = SystemClock.uptimeMillis();
13041 final long uptimeSince = curUptime - mLastPowerCheckUptime;
13042 mLastPowerCheckRealtime = curRealtime;
13043 mLastPowerCheckUptime = curUptime;
13044 if (realtimeSince < WAKE_LOCK_MIN_CHECK_DURATION) {
13045 doWakeKills = false;
13046 }
13047 if (uptimeSince < CPU_MIN_CHECK_DURATION) {
13048 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013049 }
13050 int i = mLruProcesses.size();
13051 while (i > 0) {
13052 i--;
13053 ProcessRecord app = mLruProcesses.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -070013054 if (!app.keeping) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013055 long wtime;
13056 synchronized (stats) {
13057 wtime = stats.getProcessWakeTime(app.info.uid,
13058 app.pid, curRealtime);
13059 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070013060 long wtimeUsed = wtime - app.lastWakeTime;
13061 long cputimeUsed = app.curCpuTime - app.lastCpuTime;
13062 if (DEBUG_POWER) {
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070013063 StringBuilder sb = new StringBuilder(128);
13064 sb.append("Wake for ");
13065 app.toShortString(sb);
13066 sb.append(": over ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070013067 TimeUtils.formatDuration(realtimeSince, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070013068 sb.append(" used ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070013069 TimeUtils.formatDuration(wtimeUsed, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070013070 sb.append(" (");
Dianne Hackborn287952c2010-09-22 22:34:31 -070013071 sb.append((wtimeUsed*100)/realtimeSince);
13072 sb.append("%)");
13073 Slog.i(TAG, sb.toString());
13074 sb.setLength(0);
13075 sb.append("CPU for ");
13076 app.toShortString(sb);
13077 sb.append(": over ");
13078 TimeUtils.formatDuration(uptimeSince, sb);
13079 sb.append(" used ");
13080 TimeUtils.formatDuration(cputimeUsed, sb);
13081 sb.append(" (");
13082 sb.append((cputimeUsed*100)/uptimeSince);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070013083 sb.append("%)");
13084 Slog.i(TAG, sb.toString());
13085 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013086 // If a process has held a wake lock for more
13087 // than 50% of the time during this period,
13088 // that sounds pad. Kill!
Dianne Hackborn287952c2010-09-22 22:34:31 -070013089 if (doWakeKills && realtimeSince > 0
13090 && ((wtimeUsed*100)/realtimeSince) >= 50) {
13091 synchronized (stats) {
13092 stats.reportExcessiveWakeLocked(app.info.uid, app.processName,
13093 realtimeSince, wtimeUsed);
13094 }
13095 Slog.w(TAG, "Excessive wake lock in " + app.processName
13096 + " (pid " + app.pid + "): held " + wtimeUsed
13097 + " during " + realtimeSince);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013098 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13099 app.processName, app.setAdj, "excessive wake lock");
13100 Process.killProcessQuiet(app.pid);
Dianne Hackborn287952c2010-09-22 22:34:31 -070013101 } else if (doCpuKills && uptimeSince > 0
13102 && ((cputimeUsed*100)/uptimeSince) >= 50) {
13103 synchronized (stats) {
13104 stats.reportExcessiveCpuLocked(app.info.uid, app.processName,
13105 uptimeSince, cputimeUsed);
13106 }
13107 Slog.w(TAG, "Excessive CPU in " + app.processName
13108 + " (pid " + app.pid + "): used " + cputimeUsed
13109 + " during " + uptimeSince);
13110 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13111 app.processName, app.setAdj, "excessive cpu");
13112 Process.killProcessQuiet(app.pid);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013113 } else {
13114 app.lastWakeTime = wtime;
Dianne Hackborn287952c2010-09-22 22:34:31 -070013115 app.lastCpuTime = app.curCpuTime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013116 }
13117 }
13118 }
13119 }
13120
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013121 private final void updateOomAdjLocked(
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013122 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013123 app.hiddenAdj = hiddenAdj;
13124
13125 if (app.thread == null) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013126 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013127 }
13128
Dianne Hackborn287952c2010-09-22 22:34:31 -070013129 final boolean wasKeeping = app.keeping;
13130
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013131 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013132
Jeff Brown10e89712011-07-08 18:52:57 -070013133 if (app.curRawAdj != app.setRawAdj) {
13134 if (app.curRawAdj > FOREGROUND_APP_ADJ
13135 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
13136 // If this app is transitioning from foreground to
13137 // non-foreground, have it do a gc.
13138 scheduleAppGcLocked(app);
13139 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
13140 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
13141 // Likewise do a gc when an app is moving in to the
13142 // background (such as a service stopping).
13143 scheduleAppGcLocked(app);
13144 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070013145
Jeff Brown10e89712011-07-08 18:52:57 -070013146 if (wasKeeping && !app.keeping) {
13147 // This app is no longer something we want to keep. Note
13148 // its current wake lock time to later know to kill it if
13149 // it is not behaving well.
13150 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
13151 synchronized (stats) {
13152 app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
13153 app.pid, SystemClock.elapsedRealtime());
13154 }
13155 app.lastCpuTime = app.curCpuTime;
13156 }
13157
13158 app.setRawAdj = app.curRawAdj;
13159 }
13160 if (adj != app.setAdj) {
13161 if (Process.setOomAdj(app.pid, adj)) {
13162 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
13163 TAG, "Set app " + app.processName +
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013164 " oom adj to " + adj + " because " + app.adjType);
Jeff Brown10e89712011-07-08 18:52:57 -070013165 app.setAdj = adj;
13166 } else {
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013167 Slog.w(TAG, "Failed setting oom adj of " + app + " to " + adj);
Jeff Brown10e89712011-07-08 18:52:57 -070013168 }
13169 }
13170 if (app.setSchedGroup != app.curSchedGroup) {
13171 app.setSchedGroup = app.curSchedGroup;
13172 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
13173 "Setting process group of " + app.processName
13174 + " to " + app.curSchedGroup);
13175 if (app.waitingToKill != null &&
13176 app.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {
13177 Slog.i(TAG, "Killing " + app.toShortString() + ": " + app.waitingToKill);
13178 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13179 app.processName, app.setAdj, app.waitingToKill);
13180 Process.killProcessQuiet(app.pid);
13181 } else {
13182 if (true) {
13183 long oldId = Binder.clearCallingIdentity();
13184 try {
13185 Process.setProcessGroup(app.pid, app.curSchedGroup);
13186 } catch (Exception e) {
13187 Slog.w(TAG, "Failed setting process group of " + app.pid
13188 + " to " + app.curSchedGroup);
13189 e.printStackTrace();
13190 } finally {
13191 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013192 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013193 } else {
Jeff Brown10e89712011-07-08 18:52:57 -070013194 if (app.thread != null) {
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013195 try {
Jeff Brown10e89712011-07-08 18:52:57 -070013196 app.thread.setSchedulingGroup(app.curSchedGroup);
13197 } catch (RemoteException e) {
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013198 }
13199 }
13200 }
13201 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013202 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013203 }
13204
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013205 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013206 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013207 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013208 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013209 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013210 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013211 }
13212 }
13213 return resumedActivity;
13214 }
13215
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013216 private final void updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013217 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013218 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
13219 int curAdj = app.curAdj;
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013220 final boolean wasHidden = curAdj >= HIDDEN_APP_MIN_ADJ
13221 && curAdj <= HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013222
13223 mAdjSeq++;
13224
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013225 updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
13226 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
13227 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
13228 if (nowHidden != wasHidden) {
13229 // Changed to/from hidden state, so apps after it in the LRU
13230 // list may also be changed.
13231 updateOomAdjLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013232 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013233 }
13234
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013235 final void updateOomAdjLocked() {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013236 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013237 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
13238
13239 if (false) {
13240 RuntimeException e = new RuntimeException();
13241 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080013242 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013243 }
13244
13245 mAdjSeq++;
13246
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013247 // Let's determine how many processes we have running vs.
13248 // how many slots we have for background processes; we may want
13249 // to put multiple processes in a slot of there are enough of
13250 // them.
13251 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
13252 int factor = (mLruProcesses.size()-4)/numSlots;
13253 if (factor < 1) factor = 1;
13254 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070013255 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013256
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013257 // First update the OOM adjustment for each of the
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013258 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013259 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013260 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013261 int numBg = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013262 while (i > 0) {
13263 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013264 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013265 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013266 updateOomAdjLocked(app, curHiddenAdj, TOP_APP);
13267 if (curHiddenAdj < EMPTY_APP_ADJ
13268 && app.curAdj == curHiddenAdj) {
13269 step++;
13270 if (step >= factor) {
13271 step = 0;
13272 curHiddenAdj++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013273 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013274 }
13275 if (!app.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -070013276 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013277 numHidden++;
13278 if (numHidden > mProcessLimit) {
13279 Slog.i(TAG, "No longer want " + app.processName
13280 + " (pid " + app.pid + "): hidden #" + numHidden);
13281 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13282 app.processName, app.setAdj, "too many background");
13283 app.killedBackground = true;
13284 Process.killProcessQuiet(app.pid);
13285 } else {
13286 numBg++;
Dianne Hackborn8633e682010-04-22 16:03:41 -070013287 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013288 } else if (app.curAdj >= HOME_APP_ADJ) {
13289 numBg++;
Dianne Hackborn8633e682010-04-22 16:03:41 -070013290 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013291 }
13292 }
13293
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013294 // Now determine the memory trimming level of background processes.
13295 // Unfortunately we need to start at the back of the list to do this
13296 // properly. We only do this if the number of background apps we
13297 // are managing to keep around is less than half the maximum we desire;
13298 // if we are keeping a good number around, we'll let them use whatever
13299 // memory they want.
13300 if (numHidden <= (MAX_HIDDEN_APPS/2)) {
13301 final int N = mLruProcesses.size();
13302 factor = numBg/3;
13303 step = 0;
13304 int curLevel = ComponentCallbacks.TRIM_MEMORY_COMPLETE;
13305 for (i=0; i<N; i++) {
13306 ProcessRecord app = mLruProcesses.get(i);
13307 if (app.curAdj >= HIDDEN_APP_MIN_ADJ && !app.killedBackground) {
13308 if (app.trimMemoryLevel < curLevel && app.thread != null) {
13309 try {
13310 app.thread.scheduleTrimMemory(curLevel);
13311 } catch (RemoteException e) {
13312 }
13313 if (curLevel >= ComponentCallbacks.TRIM_MEMORY_COMPLETE) {
13314 // For these apps we will also finish their activities
13315 // to help them free memory.
13316 mMainStack.destroyActivitiesLocked(app, false);
13317 }
13318 }
13319 app.trimMemoryLevel = curLevel;
13320 step++;
13321 if (step >= factor) {
13322 switch (curLevel) {
13323 case ComponentCallbacks.TRIM_MEMORY_COMPLETE:
13324 curLevel = ComponentCallbacks.TRIM_MEMORY_MODERATE;
13325 break;
13326 case ComponentCallbacks.TRIM_MEMORY_MODERATE:
13327 curLevel = ComponentCallbacks.TRIM_MEMORY_BACKGROUND;
13328 break;
13329 }
13330 }
13331 } else if (app.curAdj >= PERCEPTIBLE_APP_ADJ) {
13332 if (app.trimMemoryLevel < ComponentCallbacks.TRIM_MEMORY_INVISIBLE
13333 && app.thread != null) {
13334 try {
13335 app.thread.scheduleTrimMemory(ComponentCallbacks.TRIM_MEMORY_INVISIBLE);
13336 } catch (RemoteException e) {
13337 }
13338 }
13339 app.trimMemoryLevel = ComponentCallbacks.TRIM_MEMORY_INVISIBLE;
13340 } else {
13341 app.trimMemoryLevel = 0;
13342 }
13343 }
13344 } else {
13345 final int N = mLruProcesses.size();
13346 for (i=0; i<N; i++) {
13347 ProcessRecord app = mLruProcesses.get(i);
13348 app.trimMemoryLevel = 0;
13349 }
13350 }
13351
13352 if (mAlwaysFinishActivities) {
13353 mMainStack.destroyActivitiesLocked(null, false);
13354 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013355 }
13356
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013357 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013358 synchronized (this) {
13359 int i;
13360
13361 // First remove any unused application processes whose package
13362 // has been removed.
13363 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
13364 final ProcessRecord app = mRemovedProcesses.get(i);
13365 if (app.activities.size() == 0
13366 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013367 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013368 TAG, "Exiting empty application process "
13369 + app.processName + " ("
13370 + (app.thread != null ? app.thread.asBinder() : null)
13371 + ")\n");
13372 if (app.pid > 0 && app.pid != MY_PID) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070013373 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13374 app.processName, app.setAdj, "empty");
13375 Process.killProcessQuiet(app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013376 } else {
13377 try {
13378 app.thread.scheduleExit();
13379 } catch (Exception e) {
13380 // Ignore exceptions.
13381 }
13382 }
13383 cleanUpApplicationRecordLocked(app, false, -1);
13384 mRemovedProcesses.remove(i);
13385
13386 if (app.persistent) {
13387 if (app.persistent) {
13388 addAppLocked(app.info);
13389 }
13390 }
13391 }
13392 }
13393
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013394 // Now update the oom adj for all processes.
13395 updateOomAdjLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013396 }
13397 }
13398
13399 /** This method sends the specified signal to each of the persistent apps */
13400 public void signalPersistentProcesses(int sig) throws RemoteException {
13401 if (sig != Process.SIGNAL_USR1) {
13402 throw new SecurityException("Only SIGNAL_USR1 is allowed");
13403 }
13404
13405 synchronized (this) {
13406 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
13407 != PackageManager.PERMISSION_GRANTED) {
13408 throw new SecurityException("Requires permission "
13409 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
13410 }
13411
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013412 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
13413 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013414 if (r.thread != null && r.persistent) {
13415 Process.sendSignal(r.pid, sig);
13416 }
13417 }
13418 }
13419 }
13420
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013421 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013422 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013423
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013424 try {
13425 synchronized (this) {
13426 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
13427 // its own permission.
13428 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
13429 != PackageManager.PERMISSION_GRANTED) {
13430 throw new SecurityException("Requires permission "
13431 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013432 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013433
13434 if (start && fd == null) {
13435 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013436 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013437
13438 ProcessRecord proc = null;
13439 try {
13440 int pid = Integer.parseInt(process);
13441 synchronized (mPidsSelfLocked) {
13442 proc = mPidsSelfLocked.get(pid);
13443 }
13444 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013445 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013446
13447 if (proc == null) {
13448 HashMap<String, SparseArray<ProcessRecord>> all
13449 = mProcessNames.getMap();
13450 SparseArray<ProcessRecord> procs = all.get(process);
13451 if (procs != null && procs.size() > 0) {
13452 proc = procs.valueAt(0);
13453 }
13454 }
13455
13456 if (proc == null || proc.thread == null) {
13457 throw new IllegalArgumentException("Unknown process: " + process);
13458 }
13459
Dianne Hackbornf02e57b2011-03-01 22:21:04 -080013460 boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
13461 if (!isDebuggable) {
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013462 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
13463 throw new SecurityException("Process not debuggable: " + proc);
13464 }
13465 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013466
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013467 proc.thread.profilerControl(start, path, fd);
13468 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013469 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013470 }
13471 } catch (RemoteException e) {
13472 throw new IllegalStateException("Process disappeared");
13473 } finally {
13474 if (fd != null) {
13475 try {
13476 fd.close();
13477 } catch (IOException e) {
13478 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013479 }
13480 }
13481 }
Andy McFadden824c5102010-07-09 16:26:57 -070013482
13483 public boolean dumpHeap(String process, boolean managed,
13484 String path, ParcelFileDescriptor fd) throws RemoteException {
13485
13486 try {
13487 synchronized (this) {
13488 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
13489 // its own permission (same as profileControl).
13490 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
13491 != PackageManager.PERMISSION_GRANTED) {
13492 throw new SecurityException("Requires permission "
13493 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
13494 }
13495
13496 if (fd == null) {
13497 throw new IllegalArgumentException("null fd");
13498 }
13499
13500 ProcessRecord proc = null;
13501 try {
13502 int pid = Integer.parseInt(process);
13503 synchronized (mPidsSelfLocked) {
13504 proc = mPidsSelfLocked.get(pid);
13505 }
13506 } catch (NumberFormatException e) {
13507 }
13508
13509 if (proc == null) {
13510 HashMap<String, SparseArray<ProcessRecord>> all
13511 = mProcessNames.getMap();
13512 SparseArray<ProcessRecord> procs = all.get(process);
13513 if (procs != null && procs.size() > 0) {
13514 proc = procs.valueAt(0);
13515 }
13516 }
13517
13518 if (proc == null || proc.thread == null) {
13519 throw new IllegalArgumentException("Unknown process: " + process);
13520 }
13521
Dianne Hackbornf02e57b2011-03-01 22:21:04 -080013522 boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
13523 if (!isDebuggable) {
Andy McFadden824c5102010-07-09 16:26:57 -070013524 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
13525 throw new SecurityException("Process not debuggable: " + proc);
13526 }
13527 }
13528
13529 proc.thread.dumpHeap(managed, path, fd);
13530 fd = null;
13531 return true;
13532 }
13533 } catch (RemoteException e) {
13534 throw new IllegalStateException("Process disappeared");
13535 } finally {
13536 if (fd != null) {
13537 try {
13538 fd.close();
13539 } catch (IOException e) {
13540 }
13541 }
13542 }
13543 }
13544
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013545 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
13546 public void monitor() {
13547 synchronized (this) { }
13548 }
Svetoslav Ganov54d068e2011-03-02 12:58:40 -080013549
13550 public void onCoreSettingsChange(Bundle settings) {
13551 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
13552 ProcessRecord processRecord = mLruProcesses.get(i);
13553 try {
13554 if (processRecord.thread != null) {
13555 processRecord.thread.setCoreSettings(settings);
13556 }
13557 } catch (RemoteException re) {
13558 /* ignore */
13559 }
13560 }
13561 }
Amith Yamasani4b2e9342011-03-31 12:38:53 -070013562
13563 // Multi-user methods
13564
13565 public boolean switchUser(int userid) {
13566 // TODO
13567 return true;
13568 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013569}