blob: 0924b862c251f636e327cccccbfa4efba4f77e5a [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006-2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.am;
18
Dianne Hackborn860755f2010-06-03 18:47:52 -070019import com.android.internal.R;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080020import com.android.internal.os.BatteryStatsImpl;
Dianne Hackborn45ce8642011-07-14 16:10:16 -070021import com.android.internal.os.ProcessStats;
Dianne Hackbornde7faf62009-06-30 13:27:30 -070022import com.android.server.AttributeCache;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080023import com.android.server.IntentResolver;
24import com.android.server.ProcessMap;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080025import com.android.server.SystemServer;
26import com.android.server.Watchdog;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070027import com.android.server.am.ActivityStack.ActivityState;
Dianne Hackborna924dc0d2011-02-17 14:22:17 -080028import com.android.server.wm.WindowManagerService;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029
Dianne Hackborndd71fc82009-12-16 19:24:32 -080030import dalvik.system.Zygote;
31
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032import android.app.Activity;
33import android.app.ActivityManager;
34import android.app.ActivityManagerNative;
35import android.app.ActivityThread;
36import android.app.AlertDialog;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070037import android.app.AppGlobals;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020038import android.app.ApplicationErrorReport;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039import android.app.Dialog;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070040import android.app.IActivityController;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041import android.app.IActivityWatcher;
42import android.app.IApplicationThread;
43import android.app.IInstrumentationWatcher;
Dianne Hackborn860755f2010-06-03 18:47:52 -070044import android.app.INotificationManager;
Jeff Sharkeya4620792011-05-20 15:29:23 -070045import android.app.IProcessObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046import android.app.IServiceConnection;
47import android.app.IThumbnailReceiver;
48import android.app.Instrumentation;
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070049import android.app.Notification;
Dianne Hackborn860755f2010-06-03 18:47:52 -070050import android.app.NotificationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080051import android.app.PendingIntent;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070052import android.app.Service;
Christopher Tate45281862010-03-05 15:46:30 -080053import android.app.backup.IBackupManager;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020054import android.content.ActivityNotFoundException;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080055import android.content.BroadcastReceiver;
Dianne Hackbornce86ba82011-07-13 19:33:41 -070056import android.content.ComponentCallbacks;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080057import android.content.ComponentName;
58import android.content.ContentResolver;
59import android.content.Context;
Christian Mehlmauer7664e202010-07-20 08:46:17 +020060import android.content.DialogInterface;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080061import android.content.Intent;
62import android.content.IntentFilter;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070063import android.content.IIntentReceiver;
64import android.content.IIntentSender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -070065import android.content.IntentSender;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080066import android.content.pm.ActivityInfo;
67import android.content.pm.ApplicationInfo;
68import android.content.pm.ConfigurationInfo;
69import android.content.pm.IPackageDataObserver;
70import android.content.pm.IPackageManager;
71import android.content.pm.InstrumentationInfo;
Dan Egnor66c40e72010-01-26 16:23:11 -080072import android.content.pm.PackageInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080073import android.content.pm.PackageManager;
Dianne Hackborn2af632f2009-07-08 14:56:37 -070074import android.content.pm.PathPermission;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080075import android.content.pm.ProviderInfo;
76import android.content.pm.ResolveInfo;
77import android.content.pm.ServiceInfo;
Dianne Hackborn860755f2010-06-03 18:47:52 -070078import android.content.pm.PackageManager.NameNotFoundException;
Dianne Hackborne2515ee2011-04-27 18:52:56 -040079import android.content.res.CompatibilityInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080080import android.content.res.Configuration;
81import android.graphics.Bitmap;
Robert Greenwalt434203a2010-10-11 16:00:27 -070082import android.net.Proxy;
83import android.net.ProxyProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080084import android.net.Uri;
85import android.os.Binder;
Dan Egnor60d87622009-12-16 16:32:58 -080086import android.os.Build;
Dan Egnor42471dd2010-01-07 17:25:22 -080087import android.os.Bundle;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070088import android.os.Debug;
Dan Egnor60d87622009-12-16 16:32:58 -080089import android.os.DropBoxManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080090import android.os.Environment;
Dan Egnor42471dd2010-01-07 17:25:22 -080091import android.os.FileObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080092import android.os.FileUtils;
93import android.os.Handler;
94import android.os.IBinder;
95import android.os.IPermissionController;
96import android.os.Looper;
97import android.os.Message;
98import android.os.Parcel;
99import android.os.ParcelFileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800100import android.os.Process;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700101import android.os.RemoteCallbackList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102import android.os.RemoteException;
103import android.os.ServiceManager;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -0700104import android.os.StrictMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800105import android.os.SystemClock;
106import android.os.SystemProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800107import android.provider.Settings;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800108import android.util.EventLog;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800109import android.util.Slog;
Joe Onorato5d3bea62010-03-01 13:44:29 -0800110import android.util.Log;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800111import android.util.PrintWriterPrinter;
112import android.util.SparseArray;
Dianne Hackborn1ebccf52010-08-15 13:04:34 -0700113import android.util.TimeUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800114import android.view.Gravity;
115import android.view.LayoutInflater;
116import android.view.View;
117import android.view.WindowManager;
118import android.view.WindowManagerPolicy;
119
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700120import java.io.BufferedInputStream;
121import java.io.BufferedOutputStream;
122import java.io.DataInputStream;
123import java.io.DataOutputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800124import java.io.File;
125import java.io.FileDescriptor;
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700126import java.io.FileInputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800127import java.io.FileNotFoundException;
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700128import java.io.FileOutputStream;
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200129import java.io.IOException;
Dan Egnora455d192010-03-12 08:52:28 -0800130import java.io.InputStreamReader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800131import java.io.PrintWriter;
132import java.lang.IllegalStateException;
133import java.lang.ref.WeakReference;
134import java.util.ArrayList;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700135import java.util.Collections;
136import java.util.Comparator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800137import java.util.HashMap;
138import java.util.HashSet;
139import java.util.Iterator;
140import java.util.List;
141import java.util.Locale;
142import java.util.Map;
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -0700143import java.util.Set;
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700144import java.util.concurrent.atomic.AtomicBoolean;
145import java.util.concurrent.atomic.AtomicLong;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800146
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700147public final class ActivityManagerService extends ActivityManagerNative
148 implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800149 static final String TAG = "ActivityManager";
150 static final boolean DEBUG = false;
Dianne Hackborne2515ee2011-04-27 18:52:56 -0400151 static final boolean localLOGV = DEBUG;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800152 static final boolean DEBUG_SWITCH = localLOGV || false;
153 static final boolean DEBUG_TASKS = localLOGV || false;
154 static final boolean DEBUG_PAUSE = localLOGV || false;
155 static final boolean DEBUG_OOM_ADJ = localLOGV || false;
156 static final boolean DEBUG_TRANSITION = localLOGV || false;
157 static final boolean DEBUG_BROADCAST = localLOGV || false;
Dianne Hackborn82f3f002009-06-16 18:49:05 -0700158 static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800159 static final boolean DEBUG_SERVICE = localLOGV || false;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700160 static final boolean DEBUG_SERVICE_EXECUTING = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800161 static final boolean DEBUG_VISBILITY = localLOGV || false;
162 static final boolean DEBUG_PROCESSES = localLOGV || false;
Dianne Hackborna1e989b2009-09-01 19:54:29 -0700163 static final boolean DEBUG_PROVIDER = localLOGV || false;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800164 static final boolean DEBUG_URI_PERMISSION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800165 static final boolean DEBUG_USER_LEAVING = localLOGV || false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700166 static final boolean DEBUG_RESULTS = localLOGV || false;
Christopher Tate4a627c72011-04-01 14:43:32 -0700167 static final boolean DEBUG_BACKUP = localLOGV || true;
Dianne Hackborndc6b6352009-09-30 14:20:09 -0700168 static final boolean DEBUG_CONFIGURATION = localLOGV || false;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700169 static final boolean DEBUG_POWER = localLOGV || false;
170 static final boolean DEBUG_POWER_QUICK = DEBUG_POWER || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800171 static final boolean VALIDATE_TOKENS = false;
172 static final boolean SHOW_ACTIVITY_START_TIME = true;
173
174 // Control over CPU and battery monitoring.
175 static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes.
176 static final boolean MONITOR_CPU_USAGE = true;
177 static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds.
178 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample.
179 static final boolean MONITOR_THREAD_CPU_USAGE = false;
180
Dianne Hackborn1655be42009-05-08 14:29:01 -0700181 // The flags that are set for all calls we make to the package manager.
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700182 static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
Dianne Hackborn1655be42009-05-08 14:29:01 -0700183
Dianne Hackbornf02e57b2011-03-01 22:21:04 -0800184 private static final String SYSTEM_DEBUGGABLE = "ro.debuggable";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800185
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800186 // Maximum number of recent tasks that we can remember.
187 static final int MAX_RECENT_TASKS = 20;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700188
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700189 // Amount of time after a call to stopAppSwitches() during which we will
190 // prevent further untrusted switches from happening.
191 static final long APP_SWITCH_DELAY_TIME = 5*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800192
193 // How long we wait for a launched process to attach to the activity manager
194 // before we decide it's never going to come up for real.
195 static final int PROC_START_TIMEOUT = 10*1000;
196
Jeff Brown3f9dd282011-07-08 20:02:19 -0700197 // How long we wait for a launched process to attach to the activity manager
198 // before we decide it's never going to come up for real, when the process was
199 // started with a wrapper for instrumentation (such as Valgrind) because it
200 // could take much longer than usual.
201 static final int PROC_START_TIMEOUT_WITH_WRAPPER = 300*1000;
202
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800203 // How long to wait after going idle before forcing apps to GC.
204 static final int GC_TIMEOUT = 5*1000;
205
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700206 // The minimum amount of time between successive GC requests for a process.
207 static final int GC_MIN_INTERVAL = 60*1000;
208
Dianne Hackborn287952c2010-09-22 22:34:31 -0700209 // The rate at which we check for apps using excessive power -- 15 mins.
210 static final int POWER_CHECK_DELAY = (DEBUG_POWER_QUICK ? 2 : 15) * 60*1000;
211
212 // The minimum sample duration we will allow before deciding we have
213 // enough data on wake locks to start killing things.
214 static final int WAKE_LOCK_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
215
216 // The minimum sample duration we will allow before deciding we have
217 // enough data on CPU usage to start killing things.
218 static final int CPU_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700219
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800220 // How long we allow a receiver to run before giving up on it.
221 static final int BROADCAST_TIMEOUT = 10*1000;
222
223 // How long we wait for a service to finish executing.
224 static final int SERVICE_TIMEOUT = 20*1000;
225
226 // How long a service needs to be running until restarting its process
227 // is no longer considered to be a relaunch of the service.
228 static final int SERVICE_RESTART_DURATION = 5*1000;
229
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700230 // How long a service needs to be running until it will start back at
231 // SERVICE_RESTART_DURATION after being killed.
232 static final int SERVICE_RESET_RUN_DURATION = 60*1000;
233
234 // Multiplying factor to increase restart duration time by, for each time
235 // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
236 static final int SERVICE_RESTART_DURATION_FACTOR = 4;
237
238 // The minimum amount of time between restarting services that we allow.
239 // That is, when multiple services are restarting, we won't allow each
240 // to restart less than this amount of time from the last one.
241 static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
242
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800243 // Maximum amount of time for there to be no activity on a service before
244 // we consider it non-essential and allow its process to go on the
245 // LRU background list.
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700246 static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800247
248 // How long we wait until we timeout on key dispatching.
249 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
250
251 // The minimum time we allow between crashes, for us to consider this
252 // application to be bad and stop and its services and reject broadcasts.
253 static final int MIN_CRASH_INTERVAL = 60*1000;
254
255 // How long we wait until we timeout on key dispatching during instrumentation.
256 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
257
258 // OOM adjustments for processes in various states:
259
260 // This is a process without anything currently running in it. Definitely
261 // the first to go! Value set in system/rootdir/init.rc on startup.
262 // This value is initalized in the constructor, careful when refering to
263 // this static variable externally.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800264 static final int EMPTY_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800265
266 // This is a process only hosting activities that are not visible,
267 // so it can be killed without any disruption. Value set in
268 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800269 static final int HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800270 static int HIDDEN_APP_MIN_ADJ;
271
The Android Open Source Project4df24232009-03-05 14:34:35 -0800272 // This is a process holding the home application -- we want to try
273 // avoiding killing it, even if it would normally be in the background,
274 // because the user interacts with it so much.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800275 static final int HOME_APP_ADJ;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800276
Christopher Tate6fa95972009-06-05 18:43:55 -0700277 // This is a process currently hosting a backup operation. Killing it
278 // is not entirely fatal but is generally a bad idea.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800279 static final int BACKUP_APP_ADJ;
Christopher Tate6fa95972009-06-05 18:43:55 -0700280
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800281 // This is a process holding a secondary server -- killing it will not
282 // have much of an impact as far as the user is concerned. Value set in
283 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800284 static final int SECONDARY_SERVER_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800285
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700286 // This is a process with a heavy-weight application. It is in the
287 // background, but we want to try to avoid killing it. Value set in
288 // system/rootdir/init.rc on startup.
289 static final int HEAVY_WEIGHT_APP_ADJ;
290
291 // This is a process only hosting components that are perceptible to the
292 // user, and we really want to avoid killing them, but they are not
293 // immediately visible. An example is background music playback. Value set in
294 // system/rootdir/init.rc on startup.
295 static final int PERCEPTIBLE_APP_ADJ;
296
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800297 // This is a process only hosting activities that are visible to the
298 // user, so we'd prefer they don't disappear. Value set in
299 // system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800300 static final int VISIBLE_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800301
302 // This is the process running the current foreground app. We'd really
303 // rather not kill it! Value set in system/rootdir/init.rc on startup.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800304 static final int FOREGROUND_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800305
306 // This is a process running a core server, such as telephony. Definitely
307 // don't want to kill it, but doing so is not completely fatal.
308 static final int CORE_SERVER_ADJ = -12;
309
310 // The system process runs at the default adjustment.
311 static final int SYSTEM_ADJ = -16;
312
313 // Memory pages are 4K.
314 static final int PAGE_SIZE = 4*1024;
315
316 // Corresponding memory levels for above adjustments.
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800317 static final int EMPTY_APP_MEM;
318 static final int HIDDEN_APP_MEM;
319 static final int HOME_APP_MEM;
320 static final int BACKUP_APP_MEM;
321 static final int SECONDARY_SERVER_MEM;
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700322 static final int HEAVY_WEIGHT_APP_MEM;
323 static final int PERCEPTIBLE_APP_MEM;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800324 static final int VISIBLE_APP_MEM;
325 static final int FOREGROUND_APP_MEM;
326
327 // The minimum number of hidden apps we want to be able to keep around,
328 // without empty apps being able to push them out of memory.
329 static final int MIN_HIDDEN_APPS = 2;
330
Dianne Hackborn8633e682010-04-22 16:03:41 -0700331 // The maximum number of hidden processes we will keep around before
332 // killing them; this is just a control to not let us go too crazy with
333 // keeping around processes on devices with large amounts of RAM.
334 static final int MAX_HIDDEN_APPS = 15;
335
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800336 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700337 // been idle for less than 15 seconds.
338 static final long CONTENT_APP_IDLE_OFFSET = 15*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800339
340 // We put empty content processes after any hidden processes that have
Dianne Hackborn906497c2010-05-10 15:57:38 -0700341 // been idle for less than 120 seconds.
342 static final long EMPTY_APP_IDLE_OFFSET = 120*1000;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800343
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700344 static int getIntProp(String name, boolean allowZero) {
345 String str = SystemProperties.get(name);
346 if (str == null) {
347 throw new IllegalArgumentException("Property not defined: " + name);
348 }
349 int val = Integer.valueOf(str);
350 if (val == 0 && !allowZero) {
351 throw new IllegalArgumentException("Property must not be zero: " + name);
352 }
353 return val;
354 }
355
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800356 static {
357 // These values are set in system/rootdir/init.rc on startup.
Dianne Hackborn32907cf2010-06-10 17:50:20 -0700358 FOREGROUND_APP_ADJ = getIntProp("ro.FOREGROUND_APP_ADJ", true);
359 VISIBLE_APP_ADJ = getIntProp("ro.VISIBLE_APP_ADJ", true);
360 PERCEPTIBLE_APP_ADJ = getIntProp("ro.PERCEPTIBLE_APP_ADJ", true);
361 HEAVY_WEIGHT_APP_ADJ = getIntProp("ro.HEAVY_WEIGHT_APP_ADJ", true);
362 SECONDARY_SERVER_ADJ = getIntProp("ro.SECONDARY_SERVER_ADJ", true);
363 BACKUP_APP_ADJ = getIntProp("ro.BACKUP_APP_ADJ", true);
364 HOME_APP_ADJ = getIntProp("ro.HOME_APP_ADJ", true);
365 HIDDEN_APP_MIN_ADJ = getIntProp("ro.HIDDEN_APP_MIN_ADJ", true);
366 EMPTY_APP_ADJ = getIntProp("ro.EMPTY_APP_ADJ", true);
367 // These days we use the last empty slot for hidden apps as well.
368 HIDDEN_APP_MAX_ADJ = EMPTY_APP_ADJ;
369 FOREGROUND_APP_MEM = getIntProp("ro.FOREGROUND_APP_MEM", false)*PAGE_SIZE;
370 VISIBLE_APP_MEM = getIntProp("ro.VISIBLE_APP_MEM", false)*PAGE_SIZE;
371 PERCEPTIBLE_APP_MEM = getIntProp("ro.PERCEPTIBLE_APP_MEM", false)*PAGE_SIZE;
372 HEAVY_WEIGHT_APP_MEM = getIntProp("ro.HEAVY_WEIGHT_APP_MEM", false)*PAGE_SIZE;
373 SECONDARY_SERVER_MEM = getIntProp("ro.SECONDARY_SERVER_MEM", false)*PAGE_SIZE;
374 BACKUP_APP_MEM = getIntProp("ro.BACKUP_APP_MEM", false)*PAGE_SIZE;
375 HOME_APP_MEM = getIntProp("ro.HOME_APP_MEM", false)*PAGE_SIZE;
376 HIDDEN_APP_MEM = getIntProp("ro.HIDDEN_APP_MEM", false)*PAGE_SIZE;
377 EMPTY_APP_MEM = getIntProp("ro.EMPTY_APP_MEM", false)*PAGE_SIZE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800378 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800379
Dan Egnor42471dd2010-01-07 17:25:22 -0800380 static final int MY_PID = Process.myPid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800381
382 static final String[] EMPTY_STRING_ARRAY = new String[0];
383
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700384 public ActivityStack mMainStack;
385
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800386 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700387 * Description of a request to start a new activity, which has been held
388 * due to app switches being disabled.
389 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700390 static class PendingActivityLaunch {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700391 ActivityRecord r;
392 ActivityRecord sourceRecord;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700393 Uri[] grantedUriPermissions;
394 int grantedMode;
395 boolean onlyIfNeeded;
396 }
397
398 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
399 = new ArrayList<PendingActivityLaunch>();
400
401 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800402 * List of all active broadcasts that are to be executed immediately
403 * (without waiting for another broadcast to finish). Currently this only
404 * contains broadcasts to registered receivers, to avoid spinning up
405 * a bunch of processes to execute IntentReceiver components.
406 */
407 final ArrayList<BroadcastRecord> mParallelBroadcasts
408 = new ArrayList<BroadcastRecord>();
409
410 /**
411 * List of all active broadcasts that are to be executed one at a time.
412 * The object at the top of the list is the currently activity broadcasts;
413 * those after it are waiting for the top to finish..
414 */
415 final ArrayList<BroadcastRecord> mOrderedBroadcasts
416 = new ArrayList<BroadcastRecord>();
417
418 /**
Dianne Hackborn12527f92009-11-11 17:39:50 -0800419 * Historical data of past broadcasts, for debugging.
420 */
421 static final int MAX_BROADCAST_HISTORY = 100;
422 final BroadcastRecord[] mBroadcastHistory
423 = new BroadcastRecord[MAX_BROADCAST_HISTORY];
424
425 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800426 * Set when we current have a BROADCAST_INTENT_MSG in flight.
427 */
428 boolean mBroadcastsScheduled = false;
429
430 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800431 * Activity we have told the window manager to have key focus.
432 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700433 ActivityRecord mFocusedActivity = null;
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700434 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800435 * List of intents that were used to start the most recent tasks.
436 */
Dianne Hackborn0c5001d2011-04-12 18:16:08 -0700437 final ArrayList<TaskRecord> mRecentTasks = new ArrayList<TaskRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800438
439 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800440 * All of the applications we currently have running organized by name.
441 * The keys are strings of the application package name (as
442 * returned by the package manager), and the keys are ApplicationRecord
443 * objects.
444 */
Dianne Hackborn0c5001d2011-04-12 18:16:08 -0700445 final ProcessMap<ProcessRecord> mProcessNames = new ProcessMap<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800446
447 /**
Dianne Hackborn860755f2010-06-03 18:47:52 -0700448 * The currently running heavy-weight process, if any.
449 */
450 ProcessRecord mHeavyWeightProcess = null;
451
452 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800453 * The last time that various processes have crashed.
454 */
455 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
456
457 /**
458 * Set of applications that we consider to be bad, and will reject
459 * incoming broadcasts from (which the user has no control over).
460 * Processes are added to this set when they have crashed twice within
461 * a minimum amount of time; they are removed from it when they are
462 * later restarted (hopefully due to some user action). The value is the
463 * time it was added to the list.
464 */
465 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
466
467 /**
468 * All of the processes we currently have running organized by pid.
469 * The keys are the pid running the application.
470 *
471 * <p>NOTE: This object is protected by its own lock, NOT the global
472 * activity manager lock!
473 */
Dianne Hackborn0c5001d2011-04-12 18:16:08 -0700474 final SparseArray<ProcessRecord> mPidsSelfLocked = new SparseArray<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800475
476 /**
477 * All of the processes that have been forced to be foreground. The key
478 * is the pid of the caller who requested it (we hold a death
479 * link on it).
480 */
481 abstract class ForegroundToken implements IBinder.DeathRecipient {
482 int pid;
483 IBinder token;
484 }
485 final SparseArray<ForegroundToken> mForegroundProcesses
486 = new SparseArray<ForegroundToken>();
487
488 /**
489 * List of records for processes that someone had tried to start before the
490 * system was ready. We don't start them at that point, but ensure they
491 * are started by the time booting is complete.
492 */
493 final ArrayList<ProcessRecord> mProcessesOnHold
494 = new ArrayList<ProcessRecord>();
495
496 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800497 * List of persistent applications that are in the process
498 * of being started.
499 */
500 final ArrayList<ProcessRecord> mPersistentStartingProcesses
501 = new ArrayList<ProcessRecord>();
502
503 /**
504 * Processes that are being forcibly torn down.
505 */
506 final ArrayList<ProcessRecord> mRemovedProcesses
507 = new ArrayList<ProcessRecord>();
508
509 /**
510 * List of running applications, sorted by recent usage.
511 * The first entry in the list is the least recently used.
512 * It contains ApplicationRecord objects. This list does NOT include
513 * any persistent application records (since we never want to exit them).
514 */
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800515 final ArrayList<ProcessRecord> mLruProcesses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800516 = new ArrayList<ProcessRecord>();
517
518 /**
519 * List of processes that should gc as soon as things are idle.
520 */
521 final ArrayList<ProcessRecord> mProcessesToGc
522 = new ArrayList<ProcessRecord>();
523
524 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -0800525 * This is the process holding what we currently consider to be
526 * the "home" activity.
527 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700528 ProcessRecord mHomeProcess;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800529
530 /**
Dianne Hackborne2515ee2011-04-27 18:52:56 -0400531 * Packages that the user has asked to have run in screen size
532 * compatibility mode instead of filling the screen.
533 */
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -0700534 final CompatModePackages mCompatModePackages;
Dianne Hackborne2515ee2011-04-27 18:52:56 -0400535
536 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800537 * Set of PendingResultRecord objects that are currently active.
538 */
539 final HashSet mPendingResultRecords = new HashSet();
540
541 /**
542 * Set of IntentSenderRecord objects that are currently active.
543 */
544 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
545 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
546
547 /**
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -0800548 * Fingerprints (hashCode()) of stack traces that we've
Brad Fitzpatrick143666f2010-06-14 12:40:21 -0700549 * already logged DropBox entries for. Guarded by itself. If
550 * something (rogue user app) forces this over
551 * MAX_DUP_SUPPRESSED_STACKS entries, the contents are cleared.
552 */
553 private final HashSet<Integer> mAlreadyLoggedViolatedStacks = new HashSet<Integer>();
554 private static final int MAX_DUP_SUPPRESSED_STACKS = 5000;
555
556 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -0700557 * Strict Mode background batched logging state.
558 *
559 * The string buffer is guarded by itself, and its lock is also
560 * used to determine if another batched write is already
561 * in-flight.
562 */
563 private final StringBuilder mStrictModeBuffer = new StringBuilder();
564
565 /**
Jeff Brown4d94a762010-09-23 11:33:28 -0700566 * True if we have a pending unexpired BROADCAST_TIMEOUT_MSG posted to our handler.
567 */
568 private boolean mPendingBroadcastTimeoutMessage;
569
570 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800571 * Intent broadcast that we have tried to start, but are
572 * waiting for its application's process to be created. We only
573 * need one (instead of a list) because we always process broadcasts
574 * one at a time, so no others can be started while waiting for this
575 * one.
576 */
577 BroadcastRecord mPendingBroadcast = null;
578
579 /**
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700580 * The receiver index that is pending, to restart the broadcast if needed.
581 */
582 int mPendingBroadcastRecvIndex;
583
584 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800585 * Keeps track of all IIntentReceivers that have been registered for
586 * broadcasts. Hash keys are the receiver IBinder, hash value is
587 * a ReceiverList.
588 */
589 final HashMap mRegisteredReceivers = new HashMap();
590
591 /**
592 * Resolver for broadcast intents to registered receivers.
593 * Holds BroadcastFilter (subclass of IntentFilter).
594 */
595 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
596 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
597 @Override
598 protected boolean allowFilterResult(
599 BroadcastFilter filter, List<BroadcastFilter> dest) {
600 IBinder target = filter.receiverList.receiver.asBinder();
601 for (int i=dest.size()-1; i>=0; i--) {
602 if (dest.get(i).receiverList.receiver.asBinder() == target) {
603 return false;
604 }
605 }
606 return true;
607 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -0700608
609 @Override
610 protected String packageForFilter(BroadcastFilter filter) {
611 return filter.packageName;
612 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800613 };
614
615 /**
616 * State of all active sticky broadcasts. Keys are the action of the
617 * sticky Intent, values are an ArrayList of all broadcasted intents with
618 * that action (which should usually be one).
619 */
620 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
621 new HashMap<String, ArrayList<Intent>>();
622
623 /**
624 * All currently running services.
625 */
626 final HashMap<ComponentName, ServiceRecord> mServices =
627 new HashMap<ComponentName, ServiceRecord>();
628
629 /**
630 * All currently running services indexed by the Intent used to start them.
631 */
632 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
633 new HashMap<Intent.FilterComparison, ServiceRecord>();
634
635 /**
636 * All currently bound service connections. Keys are the IBinder of
637 * the client's IServiceConnection.
638 */
Dianne Hackborn43d9ac82010-08-25 15:06:25 -0700639 final HashMap<IBinder, ArrayList<ConnectionRecord>> mServiceConnections
640 = new HashMap<IBinder, ArrayList<ConnectionRecord>>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800641
642 /**
643 * List of services that we have been asked to start,
644 * but haven't yet been able to. It is used to hold start requests
645 * while waiting for their corresponding application thread to get
646 * going.
647 */
648 final ArrayList<ServiceRecord> mPendingServices
649 = new ArrayList<ServiceRecord>();
650
651 /**
652 * List of services that are scheduled to restart following a crash.
653 */
654 final ArrayList<ServiceRecord> mRestartingServices
655 = new ArrayList<ServiceRecord>();
656
657 /**
658 * List of services that are in the process of being stopped.
659 */
660 final ArrayList<ServiceRecord> mStoppingServices
661 = new ArrayList<ServiceRecord>();
662
663 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700664 * Backup/restore process management
665 */
666 String mBackupAppName = null;
667 BackupRecord mBackupTarget = null;
668
669 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800670 * List of PendingThumbnailsRecord objects of clients who are still
671 * waiting to receive all of the thumbnails for a task.
672 */
673 final ArrayList mPendingThumbnails = new ArrayList();
674
675 /**
676 * List of HistoryRecord objects that have been finished and must
677 * still report back to a pending thumbnail receiver.
678 */
679 final ArrayList mCancelledThumbnails = new ArrayList();
680
681 /**
682 * All of the currently running global content providers. Keys are a
683 * string containing the provider name and values are a
684 * ContentProviderRecord object containing the data about it. Note
685 * that a single provider may be published under multiple names, so
686 * there may be multiple entries here for a single one in mProvidersByClass.
687 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700688 final HashMap<String, ContentProviderRecord> mProvidersByName
689 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800690
691 /**
692 * All of the currently running global content providers. Keys are a
693 * string containing the provider's implementation class and values are a
694 * ContentProviderRecord object containing the data about it.
695 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700696 final HashMap<String, ContentProviderRecord> mProvidersByClass
697 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800698
699 /**
700 * List of content providers who have clients waiting for them. The
701 * application is currently being launched and the provider will be
702 * removed from this list once it is published.
703 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700704 final ArrayList<ContentProviderRecord> mLaunchingProviders
705 = new ArrayList<ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800706
707 /**
708 * Global set of specific Uri permissions that have been granted.
709 */
710 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
711 = new SparseArray<HashMap<Uri, UriPermission>>();
712
Svetoslav Ganov54d068e2011-03-02 12:58:40 -0800713 CoreSettingsObserver mCoreSettingsObserver;
714
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800715 /**
716 * Thread-local storage used to carry caller permissions over through
717 * indirect content-provider access.
718 * @see #ActivityManagerService.openContentUri()
719 */
720 private class Identity {
721 public int pid;
722 public int uid;
723
724 Identity(int _pid, int _uid) {
725 pid = _pid;
726 uid = _uid;
727 }
728 }
729 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
730
731 /**
732 * All information we have collected about the runtime performance of
733 * any user id that can impact battery performance.
734 */
735 final BatteryStatsService mBatteryStatsService;
736
737 /**
738 * information about component usage
739 */
740 final UsageStatsService mUsageStatsService;
741
742 /**
743 * Current configuration information. HistoryRecord objects are given
744 * a reference to this object to indicate which configuration they are
745 * currently running in, so this object must be kept immutable.
746 */
747 Configuration mConfiguration = new Configuration();
748
749 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800750 * Current sequencing integer of the configuration, for skipping old
751 * configurations.
752 */
753 int mConfigurationSeq = 0;
754
755 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700756 * Hardware-reported OpenGLES version.
757 */
758 final int GL_ES_VERSION;
759
760 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800761 * List of initialization arguments to pass to all processes when binding applications to them.
762 * For example, references to the commonly used services.
763 */
764 HashMap<String, IBinder> mAppBindArgs;
765
766 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700767 * Temporary to avoid allocations. Protected by main lock.
768 */
769 final StringBuilder mStringBuilder = new StringBuilder(256);
770
771 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800772 * Used to control how we initialize the service.
773 */
774 boolean mStartRunning = false;
775 ComponentName mTopComponent;
776 String mTopAction;
777 String mTopData;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700778 boolean mProcessesReady = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800779 boolean mSystemReady = false;
780 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700781 boolean mWaitingUpdate = false;
782 boolean mDidUpdate = false;
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700783 boolean mOnBattery = false;
Dianne Hackborn0dad3642010-09-09 21:25:35 -0700784 boolean mLaunchWarningShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800785
786 Context mContext;
787
788 int mFactoryTest;
789
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700790 boolean mCheckedForSetup;
791
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800792 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700793 * The time at which we will allow normal application switches again,
794 * after a call to {@link #stopAppSwitches()}.
795 */
796 long mAppSwitchesAllowedTime;
797
798 /**
799 * This is set to true after the first switch after mAppSwitchesAllowedTime
800 * is set; any switches after that will clear the time.
801 */
802 boolean mDidAppSwitch;
803
804 /**
Dianne Hackborn287952c2010-09-22 22:34:31 -0700805 * Last time (in realtime) at which we checked for power usage.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700806 */
Dianne Hackborn287952c2010-09-22 22:34:31 -0700807 long mLastPowerCheckRealtime;
808
809 /**
810 * Last time (in uptime) at which we checked for power usage.
811 */
812 long mLastPowerCheckUptime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700813
814 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800815 * Set while we are wanting to sleep, to prevent any
816 * activities from being started/resumed.
817 */
818 boolean mSleeping = false;
819
820 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700821 * Set if we are shutting down the system, similar to sleeping.
822 */
823 boolean mShuttingDown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800824
825 /**
826 * Task identifier that activities are currently being started
827 * in. Incremented each time a new task is created.
828 * todo: Replace this with a TokenSpace class that generates non-repeating
829 * integers that won't wrap.
830 */
831 int mCurTask = 1;
832
833 /**
834 * Current sequence id for oom_adj computation traversal.
835 */
836 int mAdjSeq = 0;
837
838 /**
Dianne Hackborn906497c2010-05-10 15:57:38 -0700839 * Current sequence id for process LRU updating.
840 */
841 int mLruSeq = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800842
843 /**
844 * System monitoring: number of processes that died since the last
845 * N procs were started.
846 */
847 int[] mProcDeaths = new int[20];
848
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700849 /**
850 * This is set if we had to do a delayed dexopt of an app before launching
851 * it, to increasing the ANR timeouts in that case.
852 */
853 boolean mDidDexOpt;
854
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800855 String mDebugApp = null;
856 boolean mWaitForDebugger = false;
857 boolean mDebugTransient = false;
858 String mOrigDebugApp = null;
859 boolean mOrigWaitForDebugger = false;
860 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700861 IActivityController mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800862
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700863 final RemoteCallbackList<IActivityWatcher> mWatchers
864 = new RemoteCallbackList<IActivityWatcher>();
Jeff Sharkeya4620792011-05-20 15:29:23 -0700865
866 final RemoteCallbackList<IProcessObserver> mProcessObservers
867 = new RemoteCallbackList<IProcessObserver>();
868
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800869 /**
870 * Callback of last caller to {@link #requestPss}.
871 */
872 Runnable mRequestPssCallback;
873
874 /**
875 * Remaining processes for which we are waiting results from the last
876 * call to {@link #requestPss}.
877 */
878 final ArrayList<ProcessRecord> mRequestPssList
879 = new ArrayList<ProcessRecord>();
880
881 /**
882 * Runtime statistics collection thread. This object's lock is used to
883 * protect all related state.
884 */
885 final Thread mProcessStatsThread;
886
887 /**
888 * Used to collect process stats when showing not responding dialog.
889 * Protected by mProcessStatsThread.
890 */
891 final ProcessStats mProcessStats = new ProcessStats(
892 MONITOR_THREAD_CPU_USAGE);
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700893 final AtomicLong mLastCpuTime = new AtomicLong(0);
894 final AtomicBoolean mProcessStatsMutexFree = new AtomicBoolean(true);
895
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800896 long mLastWriteTime = 0;
897
898 /**
899 * Set to true after the system has finished booting.
900 */
901 boolean mBooted = false;
902
Dianne Hackbornce86ba82011-07-13 19:33:41 -0700903 int mProcessLimit = MAX_HIDDEN_APPS;
904 int mProcessLimitOverride = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800905
906 WindowManagerService mWindowManager;
907
908 static ActivityManagerService mSelf;
909 static ActivityThread mSystemThread;
910
911 private final class AppDeathRecipient implements IBinder.DeathRecipient {
912 final ProcessRecord mApp;
913 final int mPid;
914 final IApplicationThread mAppThread;
915
916 AppDeathRecipient(ProcessRecord app, int pid,
917 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800918 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800919 TAG, "New death recipient " + this
920 + " for thread " + thread.asBinder());
921 mApp = app;
922 mPid = pid;
923 mAppThread = thread;
924 }
925
926 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800927 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800928 TAG, "Death received in " + this
929 + " for thread " + mAppThread.asBinder());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800930 synchronized(ActivityManagerService.this) {
931 appDiedLocked(mApp, mPid, mAppThread);
932 }
933 }
934 }
935
936 static final int SHOW_ERROR_MSG = 1;
937 static final int SHOW_NOT_RESPONDING_MSG = 2;
938 static final int SHOW_FACTORY_ERROR_MSG = 3;
939 static final int UPDATE_CONFIGURATION_MSG = 4;
940 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
941 static final int WAIT_FOR_DEBUGGER_MSG = 6;
942 static final int BROADCAST_INTENT_MSG = 7;
943 static final int BROADCAST_TIMEOUT_MSG = 8;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800944 static final int SERVICE_TIMEOUT_MSG = 12;
945 static final int UPDATE_TIME_ZONE = 13;
946 static final int SHOW_UID_ERROR_MSG = 14;
947 static final int IM_FEELING_LUCKY_MSG = 15;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800948 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700949 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -0700950 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800951 static final int FINALIZE_PENDING_INTENT_MSG = 23;
Dianne Hackborn860755f2010-06-03 18:47:52 -0700952 static final int POST_HEAVY_NOTIFICATION_MSG = 24;
953 static final int CANCEL_HEAVY_NOTIFICATION_MSG = 25;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700954 static final int SHOW_STRICT_MODE_VIOLATION_MSG = 26;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700955 static final int CHECK_EXCESSIVE_WAKE_LOCKS_MSG = 27;
Robert Greenwalt03595d02010-11-02 14:08:23 -0700956 static final int CLEAR_DNS_CACHE = 28;
Robert Greenwalt434203a2010-10-11 16:00:27 -0700957 static final int UPDATE_HTTP_PROXY = 29;
Dianne Hackborn36cd41f2011-05-25 21:00:46 -0700958 static final int SHOW_COMPAT_MODE_DIALOG_MSG = 30;
Dianne Hackborn36f80f32011-05-31 18:26:45 -0700959 static final int DISPATCH_FOREGROUND_ACTIVITIES_CHANGED = 31;
960 static final int DISPATCH_PROCESS_DIED = 32;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800961
962 AlertDialog mUidAlert;
Dianne Hackborn36cd41f2011-05-25 21:00:46 -0700963 CompatModeDialog mCompatModeDialog;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800964
965 final Handler mHandler = new Handler() {
966 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800967 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800968 //}
969
970 public void handleMessage(Message msg) {
971 switch (msg.what) {
972 case SHOW_ERROR_MSG: {
973 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800974 synchronized (ActivityManagerService.this) {
975 ProcessRecord proc = (ProcessRecord)data.get("app");
976 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800977 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800978 return;
979 }
980 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -0700981 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -0800982 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800983 d.show();
984 proc.crashDialog = d;
985 } else {
986 // The device is asleep, so just pretend that the user
987 // saw a crash dialog and hit "force quit".
988 res.set(0);
989 }
990 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700991
992 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800993 } break;
994 case SHOW_NOT_RESPONDING_MSG: {
995 synchronized (ActivityManagerService.this) {
996 HashMap data = (HashMap) msg.obj;
997 ProcessRecord proc = (ProcessRecord)data.get("app");
998 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800999 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001000 return;
1001 }
The Android Open Source Project4df24232009-03-05 14:34:35 -08001002
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001003 Intent intent = new Intent("android.intent.action.ANR");
1004 if (!mProcessesReady) {
1005 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
1006 }
1007 broadcastIntentLocked(null, null, intent,
The Android Open Source Project4df24232009-03-05 14:34:35 -08001008 null, null, 0, null, null, null,
1009 false, false, MY_PID, Process.SYSTEM_UID);
1010
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001011 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001012 mContext, proc, (ActivityRecord)data.get("activity"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001013 d.show();
1014 proc.anrDialog = d;
1015 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001016
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001017 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001018 } break;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001019 case SHOW_STRICT_MODE_VIOLATION_MSG: {
1020 HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
1021 synchronized (ActivityManagerService.this) {
1022 ProcessRecord proc = (ProcessRecord) data.get("app");
1023 if (proc == null) {
1024 Slog.e(TAG, "App not found when showing strict mode dialog.");
1025 break;
1026 }
1027 if (proc.crashDialog != null) {
1028 Slog.e(TAG, "App already has strict mode dialog: " + proc);
1029 return;
1030 }
1031 AppErrorResult res = (AppErrorResult) data.get("result");
1032 if (!mSleeping && !mShuttingDown) {
1033 Dialog d = new StrictModeViolationDialog(mContext, res, proc);
1034 d.show();
1035 proc.crashDialog = d;
1036 } else {
1037 // The device is asleep, so just pretend that the user
1038 // saw a crash dialog and hit "force quit".
1039 res.set(0);
1040 }
1041 }
1042 ensureBootCompleted();
1043 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001044 case SHOW_FACTORY_ERROR_MSG: {
1045 Dialog d = new FactoryErrorDialog(
1046 mContext, msg.getData().getCharSequence("msg"));
1047 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001048 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001049 } break;
1050 case UPDATE_CONFIGURATION_MSG: {
1051 final ContentResolver resolver = mContext.getContentResolver();
1052 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
1053 } break;
1054 case GC_BACKGROUND_PROCESSES_MSG: {
1055 synchronized (ActivityManagerService.this) {
1056 performAppGcsIfAppropriateLocked();
1057 }
1058 } break;
1059 case WAIT_FOR_DEBUGGER_MSG: {
1060 synchronized (ActivityManagerService.this) {
1061 ProcessRecord app = (ProcessRecord)msg.obj;
1062 if (msg.arg1 != 0) {
1063 if (!app.waitedForDebugger) {
1064 Dialog d = new AppWaitingForDebuggerDialog(
1065 ActivityManagerService.this,
1066 mContext, app);
1067 app.waitDialog = d;
1068 app.waitedForDebugger = true;
1069 d.show();
1070 }
1071 } else {
1072 if (app.waitDialog != null) {
1073 app.waitDialog.dismiss();
1074 app.waitDialog = null;
1075 }
1076 }
1077 }
1078 } break;
1079 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001080 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001081 TAG, "Received BROADCAST_INTENT_MSG");
1082 processNextBroadcast(true);
1083 } break;
1084 case BROADCAST_TIMEOUT_MSG: {
Jeff Brown4d94a762010-09-23 11:33:28 -07001085 synchronized (ActivityManagerService.this) {
1086 broadcastTimeoutLocked(true);
Jeff Hamiltonacf84742010-05-25 22:10:18 -05001087 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001088 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001089 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001090 if (mDidDexOpt) {
1091 mDidDexOpt = false;
1092 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1093 nmsg.obj = msg.obj;
1094 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1095 return;
1096 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001097 serviceTimeout((ProcessRecord)msg.obj);
1098 } break;
1099 case UPDATE_TIME_ZONE: {
1100 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001101 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1102 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001103 if (r.thread != null) {
1104 try {
1105 r.thread.updateTimeZone();
1106 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001107 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001108 }
1109 }
1110 }
1111 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001112 } break;
Robert Greenwalt03595d02010-11-02 14:08:23 -07001113 case CLEAR_DNS_CACHE: {
1114 synchronized (ActivityManagerService.this) {
1115 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1116 ProcessRecord r = mLruProcesses.get(i);
1117 if (r.thread != null) {
1118 try {
1119 r.thread.clearDnsCache();
1120 } catch (RemoteException ex) {
1121 Slog.w(TAG, "Failed to clear dns cache for: " + r.info.processName);
1122 }
1123 }
1124 }
1125 }
1126 } break;
Robert Greenwalt434203a2010-10-11 16:00:27 -07001127 case UPDATE_HTTP_PROXY: {
1128 ProxyProperties proxy = (ProxyProperties)msg.obj;
1129 String host = "";
1130 String port = "";
1131 String exclList = "";
1132 if (proxy != null) {
1133 host = proxy.getHost();
1134 port = Integer.toString(proxy.getPort());
1135 exclList = proxy.getExclusionList();
1136 }
1137 synchronized (ActivityManagerService.this) {
1138 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1139 ProcessRecord r = mLruProcesses.get(i);
1140 if (r.thread != null) {
1141 try {
1142 r.thread.setHttpProxy(host, port, exclList);
1143 } catch (RemoteException ex) {
1144 Slog.w(TAG, "Failed to update http proxy for: " +
1145 r.info.processName);
1146 }
1147 }
1148 }
1149 }
1150 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001151 case SHOW_UID_ERROR_MSG: {
1152 // XXX This is a temporary dialog, no need to localize.
1153 AlertDialog d = new BaseErrorDialog(mContext);
1154 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1155 d.setCancelable(false);
1156 d.setTitle("System UIDs Inconsistent");
1157 d.setMessage("UIDs on the system are inconsistent, you need to wipe your data partition or your device will be unstable.");
Christian Mehlmauer7664e202010-07-20 08:46:17 +02001158 d.setButton(DialogInterface.BUTTON_POSITIVE, "I'm Feeling Lucky",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001159 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1160 mUidAlert = d;
1161 d.show();
1162 } break;
1163 case IM_FEELING_LUCKY_MSG: {
1164 if (mUidAlert != null) {
1165 mUidAlert.dismiss();
1166 mUidAlert = null;
1167 }
1168 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001169 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001170 if (mDidDexOpt) {
1171 mDidDexOpt = false;
1172 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1173 nmsg.obj = msg.obj;
1174 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1175 return;
1176 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001177 ProcessRecord app = (ProcessRecord)msg.obj;
1178 synchronized (ActivityManagerService.this) {
1179 processStartTimedOutLocked(app);
1180 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001181 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001182 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1183 synchronized (ActivityManagerService.this) {
1184 doPendingActivityLaunchesLocked(true);
1185 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001186 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001187 case KILL_APPLICATION_MSG: {
1188 synchronized (ActivityManagerService.this) {
1189 int uid = msg.arg1;
1190 boolean restart = (msg.arg2 == 1);
1191 String pkg = (String) msg.obj;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001192 forceStopPackageLocked(pkg, uid, restart, false, true);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001193 }
1194 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001195 case FINALIZE_PENDING_INTENT_MSG: {
1196 ((PendingIntentRecord)msg.obj).completeFinalize();
1197 } break;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001198 case POST_HEAVY_NOTIFICATION_MSG: {
1199 INotificationManager inm = NotificationManager.getService();
1200 if (inm == null) {
1201 return;
1202 }
1203
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001204 ActivityRecord root = (ActivityRecord)msg.obj;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001205 ProcessRecord process = root.app;
1206 if (process == null) {
1207 return;
1208 }
1209
1210 try {
1211 Context context = mContext.createPackageContext(process.info.packageName, 0);
1212 String text = mContext.getString(R.string.heavy_weight_notification,
1213 context.getApplicationInfo().loadLabel(context.getPackageManager()));
1214 Notification notification = new Notification();
1215 notification.icon = com.android.internal.R.drawable.stat_sys_adb; //context.getApplicationInfo().icon;
1216 notification.when = 0;
1217 notification.flags = Notification.FLAG_ONGOING_EVENT;
1218 notification.tickerText = text;
1219 notification.defaults = 0; // please be quiet
1220 notification.sound = null;
1221 notification.vibrate = null;
1222 notification.setLatestEventInfo(context, text,
1223 mContext.getText(R.string.heavy_weight_notification_detail),
1224 PendingIntent.getActivity(mContext, 0, root.intent,
1225 PendingIntent.FLAG_CANCEL_CURRENT));
1226
1227 try {
1228 int[] outId = new int[1];
1229 inm.enqueueNotification("android", R.string.heavy_weight_notification,
1230 notification, outId);
1231 } catch (RuntimeException e) {
1232 Slog.w(ActivityManagerService.TAG,
1233 "Error showing notification for heavy-weight app", e);
1234 } catch (RemoteException e) {
1235 }
1236 } catch (NameNotFoundException e) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07001237 Slog.w(TAG, "Unable to create context for heavy notification", e);
Dianne Hackborn860755f2010-06-03 18:47:52 -07001238 }
1239 } break;
1240 case CANCEL_HEAVY_NOTIFICATION_MSG: {
1241 INotificationManager inm = NotificationManager.getService();
1242 if (inm == null) {
1243 return;
1244 }
1245 try {
1246 inm.cancelNotification("android",
1247 R.string.heavy_weight_notification);
1248 } catch (RuntimeException e) {
1249 Slog.w(ActivityManagerService.TAG,
1250 "Error canceling notification for service", e);
1251 } catch (RemoteException e) {
1252 }
1253 } break;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001254 case CHECK_EXCESSIVE_WAKE_LOCKS_MSG: {
1255 synchronized (ActivityManagerService.this) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001256 checkExcessivePowerUsageLocked(true);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -07001257 removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001258 Message nmsg = obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
1259 sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001260 }
1261 } break;
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07001262 case SHOW_COMPAT_MODE_DIALOG_MSG: {
1263 synchronized (ActivityManagerService.this) {
1264 ActivityRecord ar = (ActivityRecord)msg.obj;
1265 if (mCompatModeDialog != null) {
1266 if (mCompatModeDialog.mAppInfo.packageName.equals(
1267 ar.info.applicationInfo.packageName)) {
1268 return;
1269 }
1270 mCompatModeDialog.dismiss();
1271 mCompatModeDialog = null;
1272 }
Dianne Hackborn29478262011-06-07 15:44:22 -07001273 if (ar != null && false) {
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07001274 if (mCompatModePackages.getPackageAskCompatModeLocked(
1275 ar.packageName)) {
1276 int mode = mCompatModePackages.computeCompatModeLocked(
1277 ar.info.applicationInfo);
1278 if (mode == ActivityManager.COMPAT_MODE_DISABLED
1279 || mode == ActivityManager.COMPAT_MODE_ENABLED) {
1280 mCompatModeDialog = new CompatModeDialog(
1281 ActivityManagerService.this, mContext,
1282 ar.info.applicationInfo);
1283 mCompatModeDialog.show();
1284 }
1285 }
1286 }
1287 }
Dianne Hackborn36f80f32011-05-31 18:26:45 -07001288 break;
1289 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07001290 case DISPATCH_FOREGROUND_ACTIVITIES_CHANGED: {
Jeff Sharkey287bd832011-05-28 19:36:26 -07001291 final int pid = msg.arg1;
1292 final int uid = msg.arg2;
1293 final boolean foregroundActivities = (Boolean) msg.obj;
1294 dispatchForegroundActivitiesChanged(pid, uid, foregroundActivities);
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07001295 break;
1296 }
1297 case DISPATCH_PROCESS_DIED: {
Jeff Sharkey287bd832011-05-28 19:36:26 -07001298 final int pid = msg.arg1;
1299 final int uid = msg.arg2;
1300 dispatchProcessDied(pid, uid);
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07001301 break;
1302 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001303 }
1304 }
1305 };
1306
1307 public static void setSystemProcess() {
1308 try {
1309 ActivityManagerService m = mSelf;
1310
1311 ServiceManager.addService("activity", m);
1312 ServiceManager.addService("meminfo", new MemBinder(m));
Chet Haase9c1e23b2011-03-24 10:51:31 -07001313 ServiceManager.addService("gfxinfo", new GraphicsBinder(m));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001314 if (MONITOR_CPU_USAGE) {
1315 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1316 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001317 ServiceManager.addService("permission", new PermissionController(m));
1318
1319 ApplicationInfo info =
1320 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001321 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001322 mSystemThread.installSystemApplicationInfo(info);
1323
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001324 synchronized (mSelf) {
1325 ProcessRecord app = mSelf.newProcessRecordLocked(
1326 mSystemThread.getApplicationThread(), info,
1327 info.processName);
1328 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001329 app.pid = MY_PID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001330 app.maxAdj = SYSTEM_ADJ;
1331 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1332 synchronized (mSelf.mPidsSelfLocked) {
1333 mSelf.mPidsSelfLocked.put(app.pid, app);
1334 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001335 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001336 }
1337 } catch (PackageManager.NameNotFoundException e) {
1338 throw new RuntimeException(
1339 "Unable to find android system package", e);
1340 }
1341 }
1342
1343 public void setWindowManager(WindowManagerService wm) {
1344 mWindowManager = wm;
1345 }
1346
1347 public static final Context main(int factoryTest) {
1348 AThread thr = new AThread();
1349 thr.start();
1350
1351 synchronized (thr) {
1352 while (thr.mService == null) {
1353 try {
1354 thr.wait();
1355 } catch (InterruptedException e) {
1356 }
1357 }
1358 }
1359
1360 ActivityManagerService m = thr.mService;
1361 mSelf = m;
1362 ActivityThread at = ActivityThread.systemMain();
1363 mSystemThread = at;
1364 Context context = at.getSystemContext();
Dianne Hackborn247fe742011-01-08 17:25:57 -08001365 context.setTheme(android.R.style.Theme_Holo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001366 m.mContext = context;
1367 m.mFactoryTest = factoryTest;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001368 m.mMainStack = new ActivityStack(m, context, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001369
1370 m.mBatteryStatsService.publish(context);
1371 m.mUsageStatsService.publish(context);
1372
1373 synchronized (thr) {
1374 thr.mReady = true;
1375 thr.notifyAll();
1376 }
1377
1378 m.startRunning(null, null, null, null);
1379
1380 return context;
1381 }
1382
1383 public static ActivityManagerService self() {
1384 return mSelf;
1385 }
1386
1387 static class AThread extends Thread {
1388 ActivityManagerService mService;
1389 boolean mReady = false;
1390
1391 public AThread() {
1392 super("ActivityManager");
1393 }
1394
1395 public void run() {
1396 Looper.prepare();
1397
1398 android.os.Process.setThreadPriority(
1399 android.os.Process.THREAD_PRIORITY_FOREGROUND);
Christopher Tate160edb32010-06-30 17:46:30 -07001400 android.os.Process.setCanSelfBackground(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001401
1402 ActivityManagerService m = new ActivityManagerService();
1403
1404 synchronized (this) {
1405 mService = m;
1406 notifyAll();
1407 }
1408
1409 synchronized (this) {
1410 while (!mReady) {
1411 try {
1412 wait();
1413 } catch (InterruptedException e) {
1414 }
1415 }
1416 }
1417
Brad Fitzpatrickec062f62010-11-03 09:56:54 -07001418 // For debug builds, log event loop stalls to dropbox for analysis.
1419 if (StrictMode.conditionallyEnableDebugLogging()) {
1420 Slog.i(TAG, "Enabled StrictMode logging for AThread's Looper");
1421 }
1422
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001423 Looper.loop();
1424 }
1425 }
1426
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001427 static class MemBinder extends Binder {
1428 ActivityManagerService mActivityManagerService;
1429 MemBinder(ActivityManagerService activityManagerService) {
1430 mActivityManagerService = activityManagerService;
1431 }
1432
1433 @Override
1434 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07001435 mActivityManagerService.dumpApplicationMemoryUsage(fd, pw, " ", args);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001436 }
1437 }
1438
Chet Haase9c1e23b2011-03-24 10:51:31 -07001439 static class GraphicsBinder extends Binder {
1440 ActivityManagerService mActivityManagerService;
1441 GraphicsBinder(ActivityManagerService activityManagerService) {
1442 mActivityManagerService = activityManagerService;
1443 }
1444
1445 @Override
1446 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07001447 mActivityManagerService.dumpGraphicsHardwareUsage(fd, pw, args);
Chet Haase9c1e23b2011-03-24 10:51:31 -07001448 }
1449 }
1450
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001451 static class CpuBinder extends Binder {
1452 ActivityManagerService mActivityManagerService;
1453 CpuBinder(ActivityManagerService activityManagerService) {
1454 mActivityManagerService = activityManagerService;
1455 }
1456
1457 @Override
1458 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1459 synchronized (mActivityManagerService.mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07001460 pw.print(mActivityManagerService.mProcessStats.printCurrentLoad());
1461 pw.print(mActivityManagerService.mProcessStats.printCurrentState(
1462 SystemClock.uptimeMillis()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001463 }
1464 }
1465 }
1466
1467 private ActivityManagerService() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001468 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001469
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001470 File dataDir = Environment.getDataDirectory();
1471 File systemDir = new File(dataDir, "system");
1472 systemDir.mkdirs();
1473 mBatteryStatsService = new BatteryStatsService(new File(
1474 systemDir, "batterystats.bin").toString());
1475 mBatteryStatsService.getActiveStatistics().readLocked();
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001476 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
Dianne Hackborn287952c2010-09-22 22:34:31 -07001477 mOnBattery = DEBUG_POWER ? true
1478 : mBatteryStatsService.getActiveStatistics().getIsOnBattery();
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001479 mBatteryStatsService.getActiveStatistics().setCallback(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001480
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001481 mUsageStatsService = new UsageStatsService(new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001482 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001483
Jack Palevichb90d28c2009-07-22 15:35:24 -07001484 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1485 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1486
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001487 mConfiguration.setToDefaults();
1488 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001489 mProcessStats.init();
1490
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07001491 mCompatModePackages = new CompatModePackages(this, systemDir);
1492
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001493 // Add ourself to the Watchdog monitors.
1494 Watchdog.getInstance().addMonitor(this);
1495
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001496 mProcessStatsThread = new Thread("ProcessStats") {
1497 public void run() {
1498 while (true) {
1499 try {
1500 try {
1501 synchronized(this) {
1502 final long now = SystemClock.uptimeMillis();
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001503 long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001504 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001505 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001506 // + ", write delay=" + nextWriteDelay);
1507 if (nextWriteDelay < nextCpuDelay) {
1508 nextCpuDelay = nextWriteDelay;
1509 }
1510 if (nextCpuDelay > 0) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001511 mProcessStatsMutexFree.set(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001512 this.wait(nextCpuDelay);
1513 }
1514 }
1515 } catch (InterruptedException e) {
1516 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001517 updateCpuStatsNow();
1518 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001519 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001520 }
1521 }
1522 }
1523 };
1524 mProcessStatsThread.start();
1525 }
1526
1527 @Override
1528 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1529 throws RemoteException {
1530 try {
1531 return super.onTransact(code, data, reply, flags);
1532 } catch (RuntimeException e) {
1533 // The activity manager only throws security exceptions, so let's
1534 // log all others.
1535 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001536 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001537 }
1538 throw e;
1539 }
1540 }
1541
1542 void updateCpuStats() {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001543 final long now = SystemClock.uptimeMillis();
1544 if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
1545 return;
1546 }
1547 if (mProcessStatsMutexFree.compareAndSet(true, false)) {
1548 synchronized (mProcessStatsThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001549 mProcessStatsThread.notify();
1550 }
1551 }
1552 }
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001553
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001554 void updateCpuStatsNow() {
1555 synchronized (mProcessStatsThread) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001556 mProcessStatsMutexFree.set(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001557 final long now = SystemClock.uptimeMillis();
1558 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001559
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001560 if (MONITOR_CPU_USAGE &&
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001561 mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
1562 mLastCpuTime.set(now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001563 haveNewCpuStats = true;
1564 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001565 //Slog.i(TAG, mProcessStats.printCurrentState());
1566 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001567 // + mProcessStats.getTotalCpuPercent() + "%");
1568
Joe Onorato8a9b2202010-02-26 18:56:32 -08001569 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001570 if ("true".equals(SystemProperties.get("events.cpu"))) {
1571 int user = mProcessStats.getLastUserTime();
1572 int system = mProcessStats.getLastSystemTime();
1573 int iowait = mProcessStats.getLastIoWaitTime();
1574 int irq = mProcessStats.getLastIrqTime();
1575 int softIrq = mProcessStats.getLastSoftIrqTime();
1576 int idle = mProcessStats.getLastIdleTime();
1577
1578 int total = user + system + iowait + irq + softIrq + idle;
1579 if (total == 0) total = 1;
1580
Doug Zongker2bec3d42009-12-04 12:52:44 -08001581 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001582 ((user+system+iowait+irq+softIrq) * 100) / total,
1583 (user * 100) / total,
1584 (system * 100) / total,
1585 (iowait * 100) / total,
1586 (irq * 100) / total,
1587 (softIrq * 100) / total);
1588 }
1589 }
1590
Amith Yamasanie43530a2009-08-21 13:11:37 -07001591 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001592 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001593 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001594 synchronized(mPidsSelfLocked) {
1595 if (haveNewCpuStats) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001596 if (mOnBattery) {
1597 int perc = bstats.startAddingCpuLocked();
1598 int totalUTime = 0;
1599 int totalSTime = 0;
Dianne Hackborn287952c2010-09-22 22:34:31 -07001600 final int N = mProcessStats.countStats();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001601 for (int i=0; i<N; i++) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001602 ProcessStats.Stats st = mProcessStats.getStats(i);
1603 if (!st.working) {
1604 continue;
1605 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001606 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001607 int otherUTime = (st.rel_utime*perc)/100;
1608 int otherSTime = (st.rel_stime*perc)/100;
1609 totalUTime += otherUTime;
1610 totalSTime += otherSTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001611 if (pr != null) {
1612 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001613 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1614 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001615 ps.addSpeedStepTimes(cpuSpeedTimes);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001616 pr.curCpuTime += (st.rel_utime+st.rel_stime) * 10;
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001617 } else {
1618 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001619 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001620 if (ps != null) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001621 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1622 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001623 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001624 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001625 }
1626 }
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001627 bstats.finishAddingCpuLocked(perc, totalUTime,
1628 totalSTime, cpuSpeedTimes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001629 }
1630 }
1631 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001632
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001633 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1634 mLastWriteTime = now;
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001635 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001636 }
1637 }
1638 }
1639 }
1640
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001641 @Override
1642 public void batteryNeedsCpuUpdate() {
1643 updateCpuStatsNow();
1644 }
1645
1646 @Override
1647 public void batteryPowerChanged(boolean onBattery) {
1648 // When plugging in, update the CPU stats first before changing
1649 // the plug state.
1650 updateCpuStatsNow();
1651 synchronized (this) {
1652 synchronized(mPidsSelfLocked) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001653 mOnBattery = DEBUG_POWER ? true : onBattery;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001654 }
1655 }
1656 }
1657
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001658 /**
1659 * Initialize the application bind args. These are passed to each
1660 * process when the bindApplication() IPC is sent to the process. They're
1661 * lazily setup to make sure the services are running when they're asked for.
1662 */
1663 private HashMap<String, IBinder> getCommonServicesLocked() {
1664 if (mAppBindArgs == null) {
1665 mAppBindArgs = new HashMap<String, IBinder>();
1666
1667 // Setup the application init args
1668 mAppBindArgs.put("package", ServiceManager.getService("package"));
1669 mAppBindArgs.put("window", ServiceManager.getService("window"));
1670 mAppBindArgs.put(Context.ALARM_SERVICE,
1671 ServiceManager.getService(Context.ALARM_SERVICE));
1672 }
1673 return mAppBindArgs;
1674 }
1675
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001676 final void setFocusedActivityLocked(ActivityRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001677 if (mFocusedActivity != r) {
1678 mFocusedActivity = r;
1679 mWindowManager.setFocusedApp(r, true);
1680 }
1681 }
1682
Dianne Hackborn906497c2010-05-10 15:57:38 -07001683 private final void updateLruProcessInternalLocked(ProcessRecord app,
1684 boolean oomAdj, boolean updateActivityTime, int bestPos) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001685 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001686 int lrui = mLruProcesses.indexOf(app);
1687 if (lrui >= 0) mLruProcesses.remove(lrui);
1688
1689 int i = mLruProcesses.size()-1;
1690 int skipTop = 0;
1691
Dianne Hackborn906497c2010-05-10 15:57:38 -07001692 app.lruSeq = mLruSeq;
1693
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001694 // compute the new weight for this process.
1695 if (updateActivityTime) {
1696 app.lastActivityTime = SystemClock.uptimeMillis();
1697 }
1698 if (app.activities.size() > 0) {
1699 // If this process has activities, we more strongly want to keep
1700 // it around.
1701 app.lruWeight = app.lastActivityTime;
1702 } else if (app.pubProviders.size() > 0) {
1703 // If this process contains content providers, we want to keep
1704 // it a little more strongly.
1705 app.lruWeight = app.lastActivityTime - CONTENT_APP_IDLE_OFFSET;
1706 // Also don't let it kick out the first few "real" hidden processes.
1707 skipTop = MIN_HIDDEN_APPS;
1708 } else {
1709 // If this process doesn't have activities, we less strongly
1710 // want to keep it around, and generally want to avoid getting
1711 // in front of any very recently used activities.
1712 app.lruWeight = app.lastActivityTime - EMPTY_APP_IDLE_OFFSET;
1713 // Also don't let it kick out the first few "real" hidden processes.
1714 skipTop = MIN_HIDDEN_APPS;
1715 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001716
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001717 while (i >= 0) {
1718 ProcessRecord p = mLruProcesses.get(i);
1719 // If this app shouldn't be in front of the first N background
1720 // apps, then skip over that many that are currently hidden.
1721 if (skipTop > 0 && p.setAdj >= HIDDEN_APP_MIN_ADJ) {
1722 skipTop--;
1723 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001724 if (p.lruWeight <= app.lruWeight || i < bestPos) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001725 mLruProcesses.add(i+1, app);
1726 break;
1727 }
1728 i--;
1729 }
1730 if (i < 0) {
1731 mLruProcesses.add(0, app);
1732 }
1733
Dianne Hackborn906497c2010-05-10 15:57:38 -07001734 // If the app is currently using a content provider or service,
1735 // bump those processes as well.
1736 if (app.connections.size() > 0) {
1737 for (ConnectionRecord cr : app.connections) {
1738 if (cr.binding != null && cr.binding.service != null
1739 && cr.binding.service.app != null
1740 && cr.binding.service.app.lruSeq != mLruSeq) {
1741 updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,
1742 updateActivityTime, i+1);
1743 }
1744 }
1745 }
1746 if (app.conProviders.size() > 0) {
1747 for (ContentProviderRecord cpr : app.conProviders.keySet()) {
1748 if (cpr.app != null && cpr.app.lruSeq != mLruSeq) {
1749 updateLruProcessInternalLocked(cpr.app, oomAdj,
1750 updateActivityTime, i+1);
1751 }
1752 }
1753 }
1754
Joe Onorato8a9b2202010-02-26 18:56:32 -08001755 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001756 if (oomAdj) {
1757 updateOomAdjLocked();
1758 }
1759 }
1760
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001761 final void updateLruProcessLocked(ProcessRecord app,
Dianne Hackborn906497c2010-05-10 15:57:38 -07001762 boolean oomAdj, boolean updateActivityTime) {
1763 mLruSeq++;
1764 updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
1765 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07001766
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001767 final ProcessRecord getProcessRecordLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001768 String processName, int uid) {
1769 if (uid == Process.SYSTEM_UID) {
1770 // The system gets to run in any process. If there are multiple
1771 // processes with the same uid, just pick the first (this
1772 // should never happen).
1773 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1774 processName);
1775 return procs != null ? procs.valueAt(0) : null;
1776 }
1777 ProcessRecord proc = mProcessNames.get(processName, uid);
1778 return proc;
1779 }
1780
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001781 void ensurePackageDexOpt(String packageName) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001782 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001783 try {
1784 if (pm.performDexOpt(packageName)) {
1785 mDidDexOpt = true;
1786 }
1787 } catch (RemoteException e) {
1788 }
1789 }
1790
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001791 boolean isNextTransitionForward() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001792 int transit = mWindowManager.getPendingAppTransition();
1793 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1794 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1795 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1796 }
1797
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001798 final ProcessRecord startProcessLocked(String processName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001799 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001800 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001801 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1802 // We don't have to do anything more if:
1803 // (1) There is an existing application record; and
1804 // (2) The caller doesn't think it is dead, OR there is no thread
1805 // object attached to it so we know it couldn't have crashed; and
1806 // (3) There is a pid assigned to it, so it is either starting or
1807 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001808 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001809 + " app=" + app + " knownToBeDead=" + knownToBeDead
1810 + " thread=" + (app != null ? app.thread : null)
1811 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01001812 if (app != null && app.pid > 0) {
1813 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001814 // We already have the app running, or are waiting for it to
1815 // come up (we have a pid but not yet its thread), so keep it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001816 if (DEBUG_PROCESSES) Slog.v(TAG, "App already running: " + app);
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001817 // If this is a new package in the process, add the package to the list
1818 app.addPackage(info.packageName);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001819 return app;
1820 } else {
1821 // An application record is attached to a previous process,
1822 // clean it up now.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001823 if (DEBUG_PROCESSES) Slog.v(TAG, "App died: " + app);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001824 handleAppDiedLocked(app, true);
1825 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001826 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01001827
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001828 String hostingNameStr = hostingName != null
1829 ? hostingName.flattenToShortString() : null;
1830
1831 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1832 // If we are in the background, then check to see if this process
1833 // is bad. If so, we will just silently fail.
1834 if (mBadProcesses.get(info.processName, info.uid) != null) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001835 if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid
1836 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001837 return null;
1838 }
1839 } else {
1840 // When the user is explicitly starting a process, then clear its
1841 // crash count so that we won't make it bad until they see at
1842 // least one crash dialog again, and make the process good again
1843 // if it had been bad.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001844 if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
1845 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001846 mProcessCrashTimes.remove(info.processName, info.uid);
1847 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001848 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001849 info.processName);
1850 mBadProcesses.remove(info.processName, info.uid);
1851 if (app != null) {
1852 app.bad = false;
1853 }
1854 }
1855 }
1856
1857 if (app == null) {
1858 app = newProcessRecordLocked(null, info, processName);
1859 mProcessNames.put(processName, info.uid, app);
1860 } else {
1861 // If this is a new package in the process, add the package to the list
1862 app.addPackage(info.packageName);
1863 }
1864
1865 // If the system is not ready yet, then hold off on starting this
1866 // process until it is.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001867 if (!mProcessesReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001868 && !isAllowedWhileBooting(info)
1869 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001870 if (!mProcessesOnHold.contains(app)) {
1871 mProcessesOnHold.add(app);
1872 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001873 if (DEBUG_PROCESSES) Slog.v(TAG, "System not ready, putting on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001874 return app;
1875 }
1876
1877 startProcessLocked(app, hostingType, hostingNameStr);
1878 return (app.pid != 0) ? app : null;
1879 }
1880
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001881 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1882 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1883 }
1884
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001885 private final void startProcessLocked(ProcessRecord app,
1886 String hostingType, String hostingNameStr) {
1887 if (app.pid > 0 && app.pid != MY_PID) {
1888 synchronized (mPidsSelfLocked) {
1889 mPidsSelfLocked.remove(app.pid);
1890 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1891 }
1892 app.pid = 0;
1893 }
1894
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001895 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
1896 "startProcessLocked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001897 mProcessesOnHold.remove(app);
1898
1899 updateCpuStats();
1900
1901 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1902 mProcDeaths[0] = 0;
1903
1904 try {
1905 int uid = app.info.uid;
1906 int[] gids = null;
1907 try {
1908 gids = mContext.getPackageManager().getPackageGids(
1909 app.info.packageName);
1910 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001911 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001912 }
1913 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1914 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1915 && mTopComponent != null
1916 && app.processName.equals(mTopComponent.getPackageName())) {
1917 uid = 0;
1918 }
1919 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1920 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1921 uid = 0;
1922 }
1923 }
1924 int debugFlags = 0;
1925 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1926 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
Elliott Hughesfa36aee2011-06-17 14:39:41 -07001927 // Also turn on CheckJNI for debuggable apps. It's quite
1928 // awkward to turn on otherwise.
1929 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001930 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08001931 // Run the app in safe mode if its manifest requests so or the
1932 // system is booted in safe mode.
1933 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
1934 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08001935 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1936 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001937 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1938 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1939 }
Elliott Hughesae07ecf2011-07-06 17:33:27 -07001940 if ("1".equals(SystemProperties.get("debug.jni.logging"))) {
1941 debugFlags |= Zygote.DEBUG_ENABLE_JNI_LOGGING;
1942 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001943 if ("1".equals(SystemProperties.get("debug.assert"))) {
1944 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1945 }
Jeff Brown3f9dd282011-07-08 20:02:19 -07001946
1947 // Start the process. It will either succeed and return a result containing
1948 // the PID of the new process, or else throw a RuntimeException.
1949 Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
Elliott Hughese1dfcb72011-07-08 11:08:07 -07001950 app.processName, uid, uid, gids, debugFlags,
1951 app.info.targetSdkVersion, null);
Jeff Brown3f9dd282011-07-08 20:02:19 -07001952
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001953 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
1954 synchronized (bs) {
1955 if (bs.isOnBattery()) {
1956 app.batteryStats.incStartsLocked();
1957 }
1958 }
1959
Jeff Brown3f9dd282011-07-08 20:02:19 -07001960 EventLog.writeEvent(EventLogTags.AM_PROC_START, startResult.pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001961 app.processName, hostingType,
1962 hostingNameStr != null ? hostingNameStr : "");
1963
1964 if (app.persistent) {
Jeff Brown3f9dd282011-07-08 20:02:19 -07001965 Watchdog.getInstance().processStarted(app.processName, startResult.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001966 }
1967
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001968 StringBuilder buf = mStringBuilder;
1969 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001970 buf.append("Start proc ");
1971 buf.append(app.processName);
1972 buf.append(" for ");
1973 buf.append(hostingType);
1974 if (hostingNameStr != null) {
1975 buf.append(" ");
1976 buf.append(hostingNameStr);
1977 }
1978 buf.append(": pid=");
Jeff Brown3f9dd282011-07-08 20:02:19 -07001979 buf.append(startResult.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001980 buf.append(" uid=");
1981 buf.append(uid);
1982 buf.append(" gids={");
1983 if (gids != null) {
1984 for (int gi=0; gi<gids.length; gi++) {
1985 if (gi != 0) buf.append(", ");
1986 buf.append(gids[gi]);
1987
1988 }
1989 }
1990 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08001991 Slog.i(TAG, buf.toString());
Jeff Brown3f9dd282011-07-08 20:02:19 -07001992 app.pid = startResult.pid;
1993 app.usingWrapper = startResult.usingWrapper;
1994 app.removed = false;
1995 synchronized (mPidsSelfLocked) {
1996 this.mPidsSelfLocked.put(startResult.pid, app);
1997 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1998 msg.obj = app;
1999 mHandler.sendMessageDelayed(msg, startResult.usingWrapper
2000 ? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002001 }
2002 } catch (RuntimeException e) {
2003 // XXX do better error recovery.
2004 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002005 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002006 }
2007 }
2008
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002009 void updateUsageStats(ActivityRecord resumedComponent, boolean resumed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002010 if (resumed) {
2011 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
2012 } else {
2013 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
2014 }
2015 }
2016
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002017 boolean startHomeActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002018 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
2019 && mTopAction == null) {
2020 // We are running in factory test mode, but unable to find
2021 // the factory test app, so just sit around displaying the
2022 // error message and don't try to start anything.
2023 return false;
2024 }
2025 Intent intent = new Intent(
2026 mTopAction,
2027 mTopData != null ? Uri.parse(mTopData) : null);
2028 intent.setComponent(mTopComponent);
2029 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
2030 intent.addCategory(Intent.CATEGORY_HOME);
2031 }
2032 ActivityInfo aInfo =
2033 intent.resolveActivityInfo(mContext.getPackageManager(),
2034 STOCK_PM_FLAGS);
2035 if (aInfo != null) {
2036 intent.setComponent(new ComponentName(
2037 aInfo.applicationInfo.packageName, aInfo.name));
2038 // Don't do this if the home app is currently being
2039 // instrumented.
2040 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
2041 aInfo.applicationInfo.uid);
2042 if (app == null || app.instrumentationClass == null) {
2043 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002044 mMainStack.startActivityLocked(null, intent, null, null, 0, aInfo,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002045 null, null, 0, 0, 0, false, false, null);
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002046 }
2047 }
2048
2049
2050 return true;
2051 }
2052
2053 /**
2054 * Starts the "new version setup screen" if appropriate.
2055 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002056 void startSetupActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002057 // Only do this once per boot.
2058 if (mCheckedForSetup) {
2059 return;
2060 }
2061
2062 // We will show this screen if the current one is a different
2063 // version than the last one shown, and we are not running in
2064 // low-level factory test mode.
2065 final ContentResolver resolver = mContext.getContentResolver();
2066 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
2067 Settings.Secure.getInt(resolver,
2068 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
2069 mCheckedForSetup = true;
2070
2071 // See if we should be showing the platform update setup UI.
2072 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
2073 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
2074 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
2075
2076 // We don't allow third party apps to replace this.
2077 ResolveInfo ri = null;
2078 for (int i=0; ris != null && i<ris.size(); i++) {
2079 if ((ris.get(i).activityInfo.applicationInfo.flags
2080 & ApplicationInfo.FLAG_SYSTEM) != 0) {
2081 ri = ris.get(i);
2082 break;
2083 }
2084 }
2085
2086 if (ri != null) {
2087 String vers = ri.activityInfo.metaData != null
2088 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
2089 : null;
2090 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
2091 vers = ri.activityInfo.applicationInfo.metaData.getString(
2092 Intent.METADATA_SETUP_VERSION);
2093 }
2094 String lastVers = Settings.Secure.getString(
2095 resolver, Settings.Secure.LAST_SETUP_SHOWN);
2096 if (vers != null && !vers.equals(lastVers)) {
2097 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2098 intent.setComponent(new ComponentName(
2099 ri.activityInfo.packageName, ri.activityInfo.name));
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002100 mMainStack.startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002101 null, null, 0, 0, 0, false, false, null);
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002102 }
2103 }
2104 }
2105 }
2106
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002107 CompatibilityInfo compatibilityInfoForPackageLocked(ApplicationInfo ai) {
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002108 return mCompatModePackages.compatibilityInfoForPackageLocked(ai);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002109 }
2110
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002111 public int getFrontActivityScreenCompatMode() {
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002112 synchronized (this) {
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002113 return mCompatModePackages.getFrontActivityScreenCompatModeLocked();
2114 }
2115 }
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002116
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002117 public void setFrontActivityScreenCompatMode(int mode) {
2118 synchronized (this) {
2119 mCompatModePackages.setFrontActivityScreenCompatModeLocked(mode);
2120 }
2121 }
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002122
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002123 public int getPackageScreenCompatMode(String packageName) {
2124 synchronized (this) {
2125 return mCompatModePackages.getPackageScreenCompatModeLocked(packageName);
2126 }
2127 }
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002128
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002129 public void setPackageScreenCompatMode(String packageName, int mode) {
2130 synchronized (this) {
2131 mCompatModePackages.setPackageScreenCompatModeLocked(packageName, mode);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002132 }
2133 }
2134
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07002135 public boolean getPackageAskScreenCompat(String packageName) {
2136 synchronized (this) {
2137 return mCompatModePackages.getPackageAskCompatModeLocked(packageName);
2138 }
2139 }
2140
2141 public void setPackageAskScreenCompat(String packageName, boolean ask) {
2142 synchronized (this) {
2143 mCompatModePackages.setPackageAskCompatModeLocked(packageName, ask);
2144 }
2145 }
2146
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002147 void reportResumedActivityLocked(ActivityRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002148 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002149
2150 final int identHash = System.identityHashCode(r);
2151 updateUsageStats(r, true);
2152
2153 int i = mWatchers.beginBroadcast();
2154 while (i > 0) {
2155 i--;
2156 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2157 if (w != null) {
2158 try {
2159 w.activityResuming(identHash);
2160 } catch (RemoteException e) {
2161 }
2162 }
2163 }
2164 mWatchers.finishBroadcast();
2165 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002166
Jeff Sharkeya4620792011-05-20 15:29:23 -07002167 private void dispatchForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities) {
2168 int i = mProcessObservers.beginBroadcast();
2169 while (i > 0) {
2170 i--;
2171 final IProcessObserver observer = mProcessObservers.getBroadcastItem(i);
2172 if (observer != null) {
2173 try {
2174 observer.onForegroundActivitiesChanged(pid, uid, foregroundActivities);
2175 } catch (RemoteException e) {
2176 }
2177 }
2178 }
2179 mProcessObservers.finishBroadcast();
2180 }
2181
2182 private void dispatchProcessDied(int pid, int uid) {
2183 int i = mProcessObservers.beginBroadcast();
2184 while (i > 0) {
2185 i--;
2186 final IProcessObserver observer = mProcessObservers.getBroadcastItem(i);
2187 if (observer != null) {
2188 try {
2189 observer.onProcessDied(pid, uid);
2190 } catch (RemoteException e) {
2191 }
2192 }
2193 }
2194 mProcessObservers.finishBroadcast();
2195 }
2196
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002197 final void doPendingActivityLaunchesLocked(boolean doResume) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002198 final int N = mPendingActivityLaunches.size();
2199 if (N <= 0) {
2200 return;
2201 }
2202 for (int i=0; i<N; i++) {
2203 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002204 mMainStack.startActivityUncheckedLocked(pal.r, pal.sourceRecord,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002205 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
2206 doResume && i == (N-1));
2207 }
2208 mPendingActivityLaunches.clear();
2209 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002210
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002211 public final int startActivity(IApplicationThread caller,
2212 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2213 int grantedMode, IBinder resultTo,
2214 String resultWho, int requestCode, boolean onlyIfNeeded,
2215 boolean debug) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002216 return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002217 grantedUriPermissions, grantedMode, resultTo, resultWho,
2218 requestCode, onlyIfNeeded, debug, null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002219 }
2220
2221 public final WaitResult startActivityAndWait(IApplicationThread caller,
2222 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2223 int grantedMode, IBinder resultTo,
2224 String resultWho, int requestCode, boolean onlyIfNeeded,
2225 boolean debug) {
2226 WaitResult res = new WaitResult();
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002227 mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002228 grantedUriPermissions, grantedMode, resultTo, resultWho,
2229 requestCode, onlyIfNeeded, debug, res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002230 return res;
2231 }
2232
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002233 public final int startActivityWithConfig(IApplicationThread caller,
2234 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2235 int grantedMode, IBinder resultTo,
2236 String resultWho, int requestCode, boolean onlyIfNeeded,
2237 boolean debug, Configuration config) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002238 return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002239 grantedUriPermissions, grantedMode, resultTo, resultWho,
2240 requestCode, onlyIfNeeded, debug, null, config);
2241 }
2242
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002243 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002244 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002245 IBinder resultTo, String resultWho, int requestCode,
2246 int flagsMask, int flagsValues) {
2247 // Refuse possible leaked file descriptors
2248 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
2249 throw new IllegalArgumentException("File descriptors passed in Intent");
2250 }
2251
2252 IIntentSender sender = intent.getTarget();
2253 if (!(sender instanceof PendingIntentRecord)) {
2254 throw new IllegalArgumentException("Bad PendingIntent object");
2255 }
2256
2257 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002258
2259 synchronized (this) {
2260 // If this is coming from the currently resumed activity, it is
2261 // effectively saying that app switches are allowed at this point.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002262 if (mMainStack.mResumedActivity != null
2263 && mMainStack.mResumedActivity.info.applicationInfo.uid ==
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002264 Binder.getCallingUid()) {
2265 mAppSwitchesAllowedTime = 0;
2266 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002267 }
2268
Dianne Hackborn6c418d52011-06-29 14:05:33 -07002269 return pir.sendInner(0, fillInIntent, resolvedType, null,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002270 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
2271 }
2272
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002273 public boolean startNextMatchingActivity(IBinder callingActivity,
2274 Intent intent) {
2275 // Refuse possible leaked file descriptors
2276 if (intent != null && intent.hasFileDescriptors() == true) {
2277 throw new IllegalArgumentException("File descriptors passed in Intent");
2278 }
2279
2280 synchronized (this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07002281 ActivityRecord r = mMainStack.isInStackLocked(callingActivity);
2282 if (r == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002283 return false;
2284 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002285 if (r.app == null || r.app.thread == null) {
2286 // The caller is not running... d'oh!
2287 return false;
2288 }
2289 intent = new Intent(intent);
2290 // The caller is not allowed to change the data.
2291 intent.setDataAndType(r.intent.getData(), r.intent.getType());
2292 // And we are resetting to find the next component...
2293 intent.setComponent(null);
2294
2295 ActivityInfo aInfo = null;
2296 try {
2297 List<ResolveInfo> resolves =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002298 AppGlobals.getPackageManager().queryIntentActivities(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002299 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002300 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002301
2302 // Look for the original activity in the list...
2303 final int N = resolves != null ? resolves.size() : 0;
2304 for (int i=0; i<N; i++) {
2305 ResolveInfo rInfo = resolves.get(i);
2306 if (rInfo.activityInfo.packageName.equals(r.packageName)
2307 && rInfo.activityInfo.name.equals(r.info.name)) {
2308 // We found the current one... the next matching is
2309 // after it.
2310 i++;
2311 if (i<N) {
2312 aInfo = resolves.get(i).activityInfo;
2313 }
2314 break;
2315 }
2316 }
2317 } catch (RemoteException e) {
2318 }
2319
2320 if (aInfo == null) {
2321 // Nobody who is next!
2322 return false;
2323 }
2324
2325 intent.setComponent(new ComponentName(
2326 aInfo.applicationInfo.packageName, aInfo.name));
2327 intent.setFlags(intent.getFlags()&~(
2328 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
2329 Intent.FLAG_ACTIVITY_CLEAR_TOP|
2330 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
2331 Intent.FLAG_ACTIVITY_NEW_TASK));
2332
2333 // Okay now we need to start the new activity, replacing the
2334 // currently running activity. This is a little tricky because
2335 // we want to start the new one as if the current one is finished,
2336 // but not finish the current one first so that there is no flicker.
2337 // And thus...
2338 final boolean wasFinishing = r.finishing;
2339 r.finishing = true;
2340
2341 // Propagate reply information over to the new activity.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002342 final ActivityRecord resultTo = r.resultTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002343 final String resultWho = r.resultWho;
2344 final int requestCode = r.requestCode;
2345 r.resultTo = null;
2346 if (resultTo != null) {
2347 resultTo.removeResultsLocked(r, resultWho, requestCode);
2348 }
2349
2350 final long origId = Binder.clearCallingIdentity();
2351 // XXX we are not dealing with propagating grantedUriPermissions...
2352 // those are not yet exposed to user code, so there is no need.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002353 int res = mMainStack.startActivityLocked(r.app.thread, intent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002354 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002355 requestCode, -1, r.launchedFromUid, false, false, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002356 Binder.restoreCallingIdentity(origId);
2357
2358 r.finishing = wasFinishing;
2359 if (res != START_SUCCESS) {
2360 return false;
2361 }
2362 return true;
2363 }
2364 }
2365
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002366 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002367 Intent intent, String resolvedType, IBinder resultTo,
2368 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002369
2370 // This is so super not safe, that only the system (or okay root)
2371 // can do it.
2372 final int callingUid = Binder.getCallingUid();
2373 if (callingUid != 0 && callingUid != Process.myUid()) {
2374 throw new SecurityException(
2375 "startActivityInPackage only available to the system");
2376 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002377
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002378 return mMainStack.startActivityMayWait(null, uid, intent, resolvedType,
2379 null, 0, resultTo, resultWho, requestCode, onlyIfNeeded, false, null, null);
2380 }
2381
2382 public final int startActivities(IApplicationThread caller,
2383 Intent[] intents, String[] resolvedTypes, IBinder resultTo) {
2384 return mMainStack.startActivities(caller, -1, intents, resolvedTypes, resultTo);
2385 }
2386
2387 public final int startActivitiesInPackage(int uid,
2388 Intent[] intents, String[] resolvedTypes, IBinder resultTo) {
2389
2390 // This is so super not safe, that only the system (or okay root)
2391 // can do it.
2392 final int callingUid = Binder.getCallingUid();
2393 if (callingUid != 0 && callingUid != Process.myUid()) {
2394 throw new SecurityException(
2395 "startActivityInPackage only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002396 }
2397
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002398 return mMainStack.startActivities(null, uid, intents, resolvedTypes, resultTo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002399 }
2400
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002401 final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002402 int N = mRecentTasks.size();
Dianne Hackborn7c0e75e2010-12-21 19:15:40 -08002403 // Quick case: check if the top-most recent task is the same.
2404 if (N > 0 && mRecentTasks.get(0) == task) {
2405 return;
2406 }
2407 // Remove any existing entries that are the same kind of task.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002408 for (int i=0; i<N; i++) {
2409 TaskRecord tr = mRecentTasks.get(i);
2410 if ((task.affinity != null && task.affinity.equals(tr.affinity))
2411 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
2412 mRecentTasks.remove(i);
2413 i--;
2414 N--;
2415 if (task.intent == null) {
2416 // If the new recent task we are adding is not fully
2417 // specified, then replace it with the existing recent task.
2418 task = tr;
2419 }
2420 }
2421 }
2422 if (N >= MAX_RECENT_TASKS) {
2423 mRecentTasks.remove(N-1);
2424 }
2425 mRecentTasks.add(0, task);
2426 }
2427
2428 public void setRequestedOrientation(IBinder token,
2429 int requestedOrientation) {
2430 synchronized (this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07002431 ActivityRecord r = mMainStack.isInStackLocked(token);
2432 if (r == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002433 return;
2434 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002435 final long origId = Binder.clearCallingIdentity();
2436 mWindowManager.setAppOrientation(r, requestedOrientation);
2437 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07002438 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002439 r.mayFreezeScreenLocked(r.app) ? r : null);
2440 if (config != null) {
2441 r.frozenBeforeDestroy = true;
Dianne Hackborn31ca8542011-07-19 14:58:28 -07002442 if (!updateConfigurationLocked(config, r, false)) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002443 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002444 }
2445 }
2446 Binder.restoreCallingIdentity(origId);
2447 }
2448 }
2449
2450 public int getRequestedOrientation(IBinder token) {
2451 synchronized (this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07002452 ActivityRecord r = mMainStack.isInStackLocked(token);
2453 if (r == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002454 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
2455 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002456 return mWindowManager.getAppOrientation(r);
2457 }
2458 }
2459
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002460 /**
2461 * This is the internal entry point for handling Activity.finish().
2462 *
2463 * @param token The Binder token referencing the Activity we want to finish.
2464 * @param resultCode Result code, if any, from this Activity.
2465 * @param resultData Result data (Intent), if any, from this Activity.
2466 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11002467 * @return Returns true if the activity successfully finished, or false if it is still running.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002468 */
2469 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
2470 // Refuse possible leaked file descriptors
2471 if (resultData != null && resultData.hasFileDescriptors() == true) {
2472 throw new IllegalArgumentException("File descriptors passed in Intent");
2473 }
2474
2475 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002476 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002477 // Find the first activity that is not finishing.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002478 ActivityRecord next = mMainStack.topRunningActivityLocked(token, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002479 if (next != null) {
2480 // ask watcher if this is allowed
2481 boolean resumeOK = true;
2482 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002483 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002484 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002485 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002486 }
2487
2488 if (!resumeOK) {
2489 return false;
2490 }
2491 }
2492 }
2493 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002494 boolean res = mMainStack.requestFinishActivityLocked(token, resultCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002495 resultData, "app-request");
2496 Binder.restoreCallingIdentity(origId);
2497 return res;
2498 }
2499 }
2500
Dianne Hackborn860755f2010-06-03 18:47:52 -07002501 public final void finishHeavyWeightApp() {
2502 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2503 != PackageManager.PERMISSION_GRANTED) {
2504 String msg = "Permission Denial: finishHeavyWeightApp() from pid="
2505 + Binder.getCallingPid()
2506 + ", uid=" + Binder.getCallingUid()
2507 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2508 Slog.w(TAG, msg);
2509 throw new SecurityException(msg);
2510 }
2511
2512 synchronized(this) {
2513 if (mHeavyWeightProcess == null) {
2514 return;
2515 }
2516
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002517 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>(
Dianne Hackborn860755f2010-06-03 18:47:52 -07002518 mHeavyWeightProcess.activities);
2519 for (int i=0; i<activities.size(); i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002520 ActivityRecord r = activities.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002521 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002522 int index = mMainStack.indexOfTokenLocked(r);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002523 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002524 mMainStack.finishActivityLocked(r, index, Activity.RESULT_CANCELED,
Dianne Hackborn860755f2010-06-03 18:47:52 -07002525 null, "finish-heavy");
2526 }
2527 }
2528 }
2529
2530 mHeavyWeightProcess = null;
2531 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
2532 }
2533 }
2534
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002535 public void crashApplication(int uid, int initialPid, String packageName,
2536 String message) {
2537 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2538 != PackageManager.PERMISSION_GRANTED) {
2539 String msg = "Permission Denial: crashApplication() from pid="
2540 + Binder.getCallingPid()
2541 + ", uid=" + Binder.getCallingUid()
2542 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2543 Slog.w(TAG, msg);
2544 throw new SecurityException(msg);
2545 }
2546
2547 synchronized(this) {
2548 ProcessRecord proc = null;
2549
2550 // Figure out which process to kill. We don't trust that initialPid
2551 // still has any relation to current pids, so must scan through the
2552 // list.
2553 synchronized (mPidsSelfLocked) {
2554 for (int i=0; i<mPidsSelfLocked.size(); i++) {
2555 ProcessRecord p = mPidsSelfLocked.valueAt(i);
2556 if (p.info.uid != uid) {
2557 continue;
2558 }
2559 if (p.pid == initialPid) {
2560 proc = p;
2561 break;
2562 }
2563 for (String str : p.pkgList) {
2564 if (str.equals(packageName)) {
2565 proc = p;
2566 }
2567 }
2568 }
2569 }
2570
2571 if (proc == null) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07002572 Slog.w(TAG, "crashApplication: nothing for uid=" + uid
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002573 + " initialPid=" + initialPid
2574 + " packageName=" + packageName);
2575 return;
2576 }
2577
2578 if (proc.thread != null) {
Dianne Hackborn9f531192010-08-04 17:48:03 -07002579 if (proc.pid == Process.myPid()) {
2580 Log.w(TAG, "crashApplication: trying to crash self!");
2581 return;
2582 }
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002583 long ident = Binder.clearCallingIdentity();
2584 try {
2585 proc.thread.scheduleCrash(message);
2586 } catch (RemoteException e) {
2587 }
2588 Binder.restoreCallingIdentity(ident);
2589 }
2590 }
2591 }
2592
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002593 public final void finishSubActivity(IBinder token, String resultWho,
2594 int requestCode) {
2595 synchronized(this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07002596 ActivityRecord self = mMainStack.isInStackLocked(token);
2597 if (self == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002598 return;
2599 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002600
2601 final long origId = Binder.clearCallingIdentity();
2602
2603 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002604 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2605 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002606 if (r.resultTo == self && r.requestCode == requestCode) {
2607 if ((r.resultWho == null && resultWho == null) ||
2608 (r.resultWho != null && r.resultWho.equals(resultWho))) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002609 mMainStack.finishActivityLocked(r, i,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002610 Activity.RESULT_CANCELED, null, "request-sub");
2611 }
2612 }
2613 }
2614
2615 Binder.restoreCallingIdentity(origId);
2616 }
2617 }
2618
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002619 public boolean willActivityBeVisible(IBinder token) {
2620 synchronized(this) {
2621 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002622 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2623 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002624 if (r == token) {
2625 return true;
2626 }
2627 if (r.fullscreen && !r.finishing) {
2628 return false;
2629 }
2630 }
2631 return true;
2632 }
2633 }
2634
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002635 public void overridePendingTransition(IBinder token, String packageName,
2636 int enterAnim, int exitAnim) {
2637 synchronized(this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07002638 ActivityRecord self = mMainStack.isInStackLocked(token);
2639 if (self == null) {
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002640 return;
2641 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002642
2643 final long origId = Binder.clearCallingIdentity();
2644
2645 if (self.state == ActivityState.RESUMED
2646 || self.state == ActivityState.PAUSING) {
2647 mWindowManager.overridePendingAppTransition(packageName,
2648 enterAnim, exitAnim);
2649 }
2650
2651 Binder.restoreCallingIdentity(origId);
2652 }
2653 }
2654
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002655 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002656 * Main function for removing an existing process from the activity manager
2657 * as a result of that process going away. Clears out all connections
2658 * to the process.
2659 */
2660 private final void handleAppDiedLocked(ProcessRecord app,
2661 boolean restarting) {
2662 cleanUpApplicationRecordLocked(app, restarting, -1);
2663 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002664 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002665 }
2666
2667 // Just in case...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002668 if (mMainStack.mPausingActivity != null && mMainStack.mPausingActivity.app == app) {
2669 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " +mMainStack.mPausingActivity);
2670 mMainStack.mPausingActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002671 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002672 if (mMainStack.mLastPausedActivity != null && mMainStack.mLastPausedActivity.app == app) {
2673 mMainStack.mLastPausedActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002674 }
2675
2676 // Remove this application's activities from active lists.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002677 mMainStack.removeHistoryRecordsForAppLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002678
2679 boolean atTop = true;
2680 boolean hasVisibleActivities = false;
2681
2682 // Clean out the history list.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002683 int i = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002684 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002685 TAG, "Removing app " + app + " from history with " + i + " entries");
2686 while (i > 0) {
2687 i--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002688 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002689 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002690 TAG, "Record #" + i + " " + r + ": app=" + r.app);
2691 if (r.app == app) {
2692 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002693 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002694 TAG, "Removing this entry! frozen=" + r.haveState
2695 + " finishing=" + r.finishing);
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -08002696 r.makeFinishing();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002697 mMainStack.mHistory.remove(i);
Dianne Hackbornf26fd992011-04-08 18:14:09 -07002698 r.takeFromHistory();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002699 mWindowManager.removeAppToken(r);
2700 if (VALIDATE_TOKENS) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002701 mWindowManager.validateAppTokens(mMainStack.mHistory);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002702 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002703 r.removeUriPermissionsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002704
2705 } else {
2706 // We have the current state for this activity, so
2707 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002708 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002709 TAG, "Keeping entry, setting app to null");
2710 if (r.visible) {
2711 hasVisibleActivities = true;
2712 }
2713 r.app = null;
2714 r.nowVisible = false;
2715 if (!r.haveState) {
2716 r.icicle = null;
2717 }
2718 }
2719
Dianne Hackbornce86ba82011-07-13 19:33:41 -07002720 r.stack.cleanUpActivityLocked(r, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002721 }
2722 atTop = false;
2723 }
2724
2725 app.activities.clear();
2726
2727 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002728 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002729 + " running instrumentation " + app.instrumentationClass);
2730 Bundle info = new Bundle();
2731 info.putString("shortMsg", "Process crashed.");
2732 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
2733 }
2734
2735 if (!restarting) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002736 if (!mMainStack.resumeTopActivityLocked(null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002737 // If there was nothing to resume, and we are not already
2738 // restarting this process, but there is a visible activity that
2739 // is hosted by the process... then make sure all visible
2740 // activities are running, taking care of restarting this
2741 // process.
2742 if (hasVisibleActivities) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002743 mMainStack.ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002744 }
2745 }
2746 }
2747 }
2748
2749 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
2750 IBinder threadBinder = thread.asBinder();
2751
2752 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002753 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2754 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002755 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
2756 return i;
2757 }
2758 }
2759 return -1;
2760 }
2761
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002762 final ProcessRecord getRecordForAppLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002763 IApplicationThread thread) {
2764 if (thread == null) {
2765 return null;
2766 }
2767
2768 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002769 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002770 }
2771
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002772 final void appDiedLocked(ProcessRecord app, int pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002773 IApplicationThread thread) {
2774
2775 mProcDeaths[0]++;
2776
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07002777 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
2778 synchronized (stats) {
2779 stats.noteProcessDiedLocked(app.info.uid, pid);
2780 }
2781
Magnus Edlund7bb25812010-02-24 15:45:06 +01002782 // Clean up already done if the process has been re-started.
2783 if (app.pid == pid && app.thread != null &&
2784 app.thread.asBinder() == thread.asBinder()) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07002785 if (!app.killedBackground) {
2786 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
2787 + ") has died.");
2788 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08002789 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002790 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002791 TAG, "Dying app: " + app + ", pid: " + pid
2792 + ", thread: " + thread.asBinder());
2793 boolean doLowMem = app.instrumentationClass == null;
2794 handleAppDiedLocked(app, false);
2795
2796 if (doLowMem) {
2797 // If there are no longer any background processes running,
2798 // and the app that died was not running instrumentation,
2799 // then tell everyone we are now low on memory.
2800 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002801 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2802 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002803 if (rec.thread != null && rec.setAdj >= HIDDEN_APP_MIN_ADJ) {
2804 haveBg = true;
2805 break;
2806 }
2807 }
2808
2809 if (!haveBg) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002810 Slog.i(TAG, "Low Memory: No more background processes.");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002811 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002812 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002813 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2814 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07002815 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002816 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
2817 // The low memory report is overriding any current
2818 // state for a GC request. Make sure to do
Dianne Hackborn32907cf2010-06-10 17:50:20 -07002819 // heavy/important/visible/foreground processes first.
2820 if (rec.setAdj <= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002821 rec.lastRequestedGc = 0;
2822 } else {
2823 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002824 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002825 rec.reportLowMemory = true;
2826 rec.lastLowMemory = now;
2827 mProcessesToGc.remove(rec);
2828 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002829 }
2830 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002831 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002832 }
2833 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01002834 } else if (app.pid != pid) {
2835 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002836 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01002837 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08002838 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002839 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002840 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002841 + thread.asBinder());
2842 }
2843 }
2844
Dan Egnor42471dd2010-01-07 17:25:22 -08002845 /**
2846 * If a stack trace dump file is configured, dump process stack traces.
Christopher Tate6ee412d2010-05-28 12:01:56 -07002847 * @param clearTraces causes the dump file to be erased prior to the new
2848 * traces being written, if true; when false, the new traces will be
2849 * appended to any existing file content.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002850 * @param firstPids of dalvik VM processes to dump stack traces for first
2851 * @param lastPids of dalvik VM processes to dump stack traces for last
Dan Egnor42471dd2010-01-07 17:25:22 -08002852 * @return file containing stack traces, or null if no dump file is configured
2853 */
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002854 public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> firstPids,
2855 ProcessStats processStats, SparseArray<Boolean> lastPids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002856 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
2857 if (tracesPath == null || tracesPath.length() == 0) {
2858 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002859 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002860
2861 File tracesFile = new File(tracesPath);
2862 try {
2863 File tracesDir = tracesFile.getParentFile();
2864 if (!tracesDir.exists()) tracesFile.mkdirs();
2865 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
2866
Christopher Tate6ee412d2010-05-28 12:01:56 -07002867 if (clearTraces && tracesFile.exists()) tracesFile.delete();
Dan Egnor42471dd2010-01-07 17:25:22 -08002868 tracesFile.createNewFile();
2869 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
2870 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002871 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08002872 return null;
2873 }
2874
2875 // Use a FileObserver to detect when traces finish writing.
2876 // The order of traces is considered important to maintain for legibility.
2877 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
2878 public synchronized void onEvent(int event, String path) { notify(); }
2879 };
2880
2881 try {
2882 observer.startWatching();
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002883
2884 // First collect all of the stacks of the most important pids.
2885 try {
2886 int num = firstPids.size();
2887 for (int i = 0; i < num; i++) {
2888 synchronized (observer) {
2889 Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT);
2890 observer.wait(200); // Wait for write-close, give up after 200msec
2891 }
2892 }
2893 } catch (InterruptedException e) {
2894 Log.wtf(TAG, e);
2895 }
2896
2897 // Next measure CPU usage.
2898 if (processStats != null) {
2899 processStats.init();
2900 System.gc();
2901 processStats.update();
2902 try {
2903 synchronized (processStats) {
2904 processStats.wait(500); // measure over 1/2 second.
2905 }
2906 } catch (InterruptedException e) {
2907 }
2908 processStats.update();
2909
2910 // We'll take the stack crawls of just the top apps using CPU.
2911 final int N = processStats.countWorkingStats();
2912 int numProcs = 0;
2913 for (int i=0; i<N && numProcs<5; i++) {
2914 ProcessStats.Stats stats = processStats.getWorkingStats(i);
2915 if (lastPids.indexOfKey(stats.pid) >= 0) {
2916 numProcs++;
2917 try {
2918 synchronized (observer) {
2919 Process.sendSignal(stats.pid, Process.SIGNAL_QUIT);
2920 observer.wait(200); // Wait for write-close, give up after 200msec
2921 }
2922 } catch (InterruptedException e) {
2923 Log.wtf(TAG, e);
2924 }
2925
2926 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002927 }
2928 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002929
2930 return tracesFile;
2931
Dan Egnor42471dd2010-01-07 17:25:22 -08002932 } finally {
2933 observer.stopWatching();
2934 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002935 }
2936
Jeff Brown4d94a762010-09-23 11:33:28 -07002937 private final class AppNotResponding implements Runnable {
2938 private final ProcessRecord mApp;
2939 private final String mAnnotation;
2940
2941 public AppNotResponding(ProcessRecord app, String annotation) {
2942 mApp = app;
2943 mAnnotation = annotation;
2944 }
2945
2946 @Override
2947 public void run() {
2948 appNotResponding(mApp, null, null, mAnnotation);
2949 }
2950 }
2951
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002952 final void appNotResponding(ProcessRecord app, ActivityRecord activity,
2953 ActivityRecord parent, final String annotation) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002954 ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
2955 SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20);
2956
Dianne Hackborn287952c2010-09-22 22:34:31 -07002957 if (mController != null) {
2958 try {
2959 // 0 == continue, -1 = kill process immediately
2960 int res = mController.appEarlyNotResponding(app.processName, app.pid, annotation);
2961 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2962 } catch (RemoteException e) {
2963 mController = null;
2964 }
2965 }
2966
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002967 long anrTime = SystemClock.uptimeMillis();
2968 if (MONITOR_CPU_USAGE) {
2969 updateCpuStatsNow();
2970 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002971
2972 synchronized (this) {
2973 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
2974 if (mShuttingDown) {
2975 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
2976 return;
2977 } else if (app.notResponding) {
2978 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
2979 return;
2980 } else if (app.crashing) {
2981 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
2982 return;
2983 }
2984
2985 // In case we come through here for the same app before completing
2986 // this one, mark as anring now so we will bail out.
2987 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08002988
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002989 // Log the ANR to the event log.
2990 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
2991 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08002992
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002993 // Dump thread traces as quickly as we can, starting with "interesting" processes.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002994 firstPids.add(app.pid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002995
2996 int parentPid = app.pid;
2997 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002998 if (parentPid != app.pid) firstPids.add(parentPid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002999
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003000 if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08003001
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003002 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
3003 ProcessRecord r = mLruProcesses.get(i);
3004 if (r != null && r.thread != null) {
3005 int pid = r.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003006 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
3007 if (r.persistent) {
3008 firstPids.add(pid);
3009 } else {
3010 lastPids.put(pid, Boolean.TRUE);
3011 }
3012 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003013 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003014 }
3015 }
3016
Dan Egnor42471dd2010-01-07 17:25:22 -08003017 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07003018 StringBuilder info = mStringBuilder;
3019 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08003020 info.append("ANR in ").append(app.processName);
3021 if (activity != null && activity.shortComponentName != null) {
3022 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07003023 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08003024 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003025 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08003026 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003027 }
Dan Egnor42471dd2010-01-07 17:25:22 -08003028 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08003029 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003030 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003031
Dianne Hackborn287952c2010-09-22 22:34:31 -07003032 final ProcessStats processStats = new ProcessStats(true);
3033
3034 File tracesFile = dumpStackTraces(true, firstPids, processStats, lastPids);
3035
Dan Egnor42471dd2010-01-07 17:25:22 -08003036 String cpuInfo = null;
3037 if (MONITOR_CPU_USAGE) {
3038 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003039 synchronized (mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003040 cpuInfo = mProcessStats.printCurrentState(anrTime);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003041 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003042 info.append(processStats.printCurrentLoad());
Dan Egnor42471dd2010-01-07 17:25:22 -08003043 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003044 }
3045
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003046 info.append(processStats.printCurrentState(anrTime));
3047
Joe Onorato8a9b2202010-02-26 18:56:32 -08003048 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08003049 if (tracesFile == null) {
3050 // There is no trace file, so dump (only) the alleged culprit's threads to the log
3051 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
3052 }
3053
3054 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
3055
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003056 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003057 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08003058 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
3059 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003060 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08003061 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
3062 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003063 }
3064 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003065 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003066 }
3067 }
3068
Dan Egnor42471dd2010-01-07 17:25:22 -08003069 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
3070 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
3071 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003072
3073 synchronized (this) {
3074 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07003075 Slog.w(TAG, "Killing " + app + ": background ANR");
3076 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
3077 app.processName, app.setAdj, "background ANR");
3078 Process.killProcessQuiet(app.pid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003079 return;
3080 }
3081
3082 // Set the app's notResponding state, and look up the errorReportReceiver
3083 makeAppNotRespondingLocked(app,
3084 activity != null ? activity.shortComponentName : null,
3085 annotation != null ? "ANR " + annotation : "ANR",
3086 info.toString());
3087
3088 // Bring up the infamous App Not Responding dialog
3089 Message msg = Message.obtain();
3090 HashMap map = new HashMap();
3091 msg.what = SHOW_NOT_RESPONDING_MSG;
3092 msg.obj = map;
3093 map.put("app", app);
3094 if (activity != null) {
3095 map.put("activity", activity);
3096 }
3097
3098 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08003099 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003100 }
3101
Dianne Hackborn0dad3642010-09-09 21:25:35 -07003102 final void showLaunchWarningLocked(final ActivityRecord cur, final ActivityRecord next) {
3103 if (!mLaunchWarningShown) {
3104 mLaunchWarningShown = true;
3105 mHandler.post(new Runnable() {
3106 @Override
3107 public void run() {
3108 synchronized (ActivityManagerService.this) {
3109 final Dialog d = new LaunchWarningWindow(mContext, cur, next);
3110 d.show();
3111 mHandler.postDelayed(new Runnable() {
3112 @Override
3113 public void run() {
3114 synchronized (ActivityManagerService.this) {
3115 d.dismiss();
3116 mLaunchWarningShown = false;
3117 }
3118 }
3119 }, 4000);
3120 }
3121 }
3122 });
3123 }
3124 }
3125
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003126 public boolean clearApplicationUserData(final String packageName,
3127 final IPackageDataObserver observer) {
3128 int uid = Binder.getCallingUid();
3129 int pid = Binder.getCallingPid();
3130 long callingId = Binder.clearCallingIdentity();
3131 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003132 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003133 int pkgUid = -1;
3134 synchronized(this) {
3135 try {
3136 pkgUid = pm.getPackageUid(packageName);
3137 } catch (RemoteException e) {
3138 }
3139 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003140 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003141 return false;
3142 }
3143 if (uid == pkgUid || checkComponentPermission(
3144 android.Manifest.permission.CLEAR_APP_USER_DATA,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08003145 pid, uid, -1, true)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003146 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003147 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003148 } else {
3149 throw new SecurityException(pid+" does not have permission:"+
3150 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
3151 "for process:"+packageName);
3152 }
3153 }
3154
3155 try {
3156 //clear application user data
3157 pm.clearApplicationUserData(packageName, observer);
3158 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
3159 Uri.fromParts("package", packageName, null));
3160 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003161 broadcastIntentInPackage("android", Process.SYSTEM_UID, intent,
3162 null, null, 0, null, null, null, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003163 } catch (RemoteException e) {
3164 }
3165 } finally {
3166 Binder.restoreCallingIdentity(callingId);
3167 }
3168 return true;
3169 }
3170
Dianne Hackborn03abb812010-01-04 18:43:19 -08003171 public void killBackgroundProcesses(final String packageName) {
3172 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
3173 != PackageManager.PERMISSION_GRANTED &&
3174 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
3175 != PackageManager.PERMISSION_GRANTED) {
3176 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003177 + Binder.getCallingPid()
3178 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08003179 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003180 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003181 throw new SecurityException(msg);
3182 }
3183
3184 long callingId = Binder.clearCallingIdentity();
3185 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003186 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003187 int pkgUid = -1;
3188 synchronized(this) {
3189 try {
3190 pkgUid = pm.getPackageUid(packageName);
3191 } catch (RemoteException e) {
3192 }
3193 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003194 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003195 return;
3196 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003197 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003198 SECONDARY_SERVER_ADJ, false, true);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003199 }
3200 } finally {
3201 Binder.restoreCallingIdentity(callingId);
3202 }
3203 }
3204
3205 public void forceStopPackage(final String packageName) {
3206 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
3207 != PackageManager.PERMISSION_GRANTED) {
3208 String msg = "Permission Denial: forceStopPackage() from pid="
3209 + Binder.getCallingPid()
3210 + ", uid=" + Binder.getCallingUid()
3211 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003212 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003213 throw new SecurityException(msg);
3214 }
3215
3216 long callingId = Binder.clearCallingIdentity();
3217 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003218 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn03abb812010-01-04 18:43:19 -08003219 int pkgUid = -1;
3220 synchronized(this) {
3221 try {
3222 pkgUid = pm.getPackageUid(packageName);
3223 } catch (RemoteException e) {
3224 }
3225 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003226 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003227 return;
3228 }
3229 forceStopPackageLocked(packageName, pkgUid);
Dianne Hackborne7f97212011-02-24 14:40:20 -08003230 try {
3231 pm.setPackageStoppedState(packageName, true);
3232 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08003233 } catch (IllegalArgumentException e) {
3234 Slog.w(TAG, "Failed trying to unstop package "
3235 + packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08003236 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003237 }
3238 } finally {
3239 Binder.restoreCallingIdentity(callingId);
3240 }
3241 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003242
3243 /*
3244 * The pkg name and uid have to be specified.
3245 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
3246 */
3247 public void killApplicationWithUid(String pkg, int uid) {
3248 if (pkg == null) {
3249 return;
3250 }
3251 // Make sure the uid is valid.
3252 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003253 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003254 return;
3255 }
3256 int callerUid = Binder.getCallingUid();
3257 // Only the system server can kill an application
3258 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07003259 // Post an aysnc message to kill the application
3260 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
3261 msg.arg1 = uid;
3262 msg.arg2 = 0;
3263 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07003264 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003265 } else {
3266 throw new SecurityException(callerUid + " cannot kill pkg: " +
3267 pkg);
3268 }
3269 }
3270
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003271 public void closeSystemDialogs(String reason) {
3272 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003273 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003274 if (reason != null) {
3275 intent.putExtra("reason", reason);
3276 }
3277
3278 final int uid = Binder.getCallingUid();
3279 final long origId = Binder.clearCallingIdentity();
3280 synchronized (this) {
3281 int i = mWatchers.beginBroadcast();
3282 while (i > 0) {
3283 i--;
3284 IActivityWatcher w = mWatchers.getBroadcastItem(i);
3285 if (w != null) {
3286 try {
3287 w.closingSystemDialogs(reason);
3288 } catch (RemoteException e) {
3289 }
3290 }
3291 }
3292 mWatchers.finishBroadcast();
3293
Dianne Hackbornffa42482009-09-23 22:20:11 -07003294 mWindowManager.closeSystemDialogs(reason);
3295
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003296 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3297 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackbornffa42482009-09-23 22:20:11 -07003298 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003299 r.stack.finishActivityLocked(r, i,
Dianne Hackbornffa42482009-09-23 22:20:11 -07003300 Activity.RESULT_CANCELED, null, "close-sys");
3301 }
3302 }
3303
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003304 broadcastIntentLocked(null, null, intent, null,
3305 null, 0, null, null, null, false, false, -1, uid);
3306 }
3307 Binder.restoreCallingIdentity(origId);
3308 }
3309
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003310 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003311 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003312 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
3313 for (int i=pids.length-1; i>=0; i--) {
3314 infos[i] = new Debug.MemoryInfo();
3315 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003316 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003317 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003318 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07003319
3320 public void killApplicationProcess(String processName, int uid) {
3321 if (processName == null) {
3322 return;
3323 }
3324
3325 int callerUid = Binder.getCallingUid();
3326 // Only the system server can kill an application
3327 if (callerUid == Process.SYSTEM_UID) {
3328 synchronized (this) {
3329 ProcessRecord app = getProcessRecordLocked(processName, uid);
Christopher Tate4a627c72011-04-01 14:43:32 -07003330 if (app != null && app.thread != null) {
Christopher Tate5e1ab332009-09-01 20:32:49 -07003331 try {
3332 app.thread.scheduleSuicide();
3333 } catch (RemoteException e) {
3334 // If the other end already died, then our work here is done.
3335 }
3336 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003337 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07003338 + processName + " / " + uid);
3339 }
3340 }
3341 } else {
3342 throw new SecurityException(callerUid + " cannot kill app process: " +
3343 processName);
3344 }
3345 }
3346
Dianne Hackborn03abb812010-01-04 18:43:19 -08003347 private void forceStopPackageLocked(final String packageName, int uid) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003348 forceStopPackageLocked(packageName, uid, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003349 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
3350 Uri.fromParts("package", packageName, null));
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003351 if (!mProcessesReady) {
3352 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
3353 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003354 intent.putExtra(Intent.EXTRA_UID, uid);
3355 broadcastIntentLocked(null, null, intent,
3356 null, null, 0, null, null, null,
3357 false, false, MY_PID, Process.SYSTEM_UID);
3358 }
3359
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003360 private final boolean killPackageProcessesLocked(String packageName, int uid,
3361 int minOomAdj, boolean callerWillRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003362 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003363
Dianne Hackborn03abb812010-01-04 18:43:19 -08003364 // Remove all processes this package may have touched: all with the
3365 // same UID (except for the system or root user), and all whose name
3366 // matches the package name.
3367 final String procNamePrefix = packageName + ":";
3368 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
3369 final int NA = apps.size();
3370 for (int ia=0; ia<NA; ia++) {
3371 ProcessRecord app = apps.valueAt(ia);
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 {
Dianne Hackborn1b64e0d2011-07-17 15:23:59 -07003613 AppDeathRecipient adr = new AppDeathRecipient(
3614 app, pid, thread);
3615 thread.asBinder().linkToDeath(adr, 0);
3616 app.deathRecipient = adr;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003617 } catch (RemoteException e) {
3618 app.resetPackageList();
3619 startProcessLocked(app, "link fail", processName);
3620 return false;
3621 }
3622
Doug Zongker2bec3d42009-12-04 12:52:44 -08003623 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003624
3625 app.thread = thread;
3626 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08003627 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
3628 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003629 app.forcingToForeground = null;
3630 app.foregroundServices = false;
3631 app.debugging = false;
3632
3633 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3634
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003635 boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003636 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003637
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003638 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003639 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003640 }
3641
Joe Onorato8a9b2202010-02-26 18:56:32 -08003642 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003643 TAG, "New app record " + app
3644 + " thread=" + thread.asBinder() + " pid=" + pid);
3645 try {
3646 int testMode = IApplicationThread.DEBUG_OFF;
3647 if (mDebugApp != null && mDebugApp.equals(processName)) {
3648 testMode = mWaitForDebugger
3649 ? IApplicationThread.DEBUG_WAIT
3650 : IApplicationThread.DEBUG_ON;
3651 app.debugging = true;
3652 if (mDebugTransient) {
3653 mDebugApp = mOrigDebugApp;
3654 mWaitForDebugger = mOrigWaitForDebugger;
3655 }
3656 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003657
Christopher Tate181fafa2009-05-14 11:12:14 -07003658 // If the app is being launched for restore or full backup, set it up specially
3659 boolean isRestrictedBackupMode = false;
3660 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
3661 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
Christopher Tate75a99702011-05-18 16:28:19 -07003662 || (mBackupTarget.backupMode == BackupRecord.RESTORE_FULL)
Christopher Tate181fafa2009-05-14 11:12:14 -07003663 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
3664 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003665
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07003666 ensurePackageDexOpt(app.instrumentationInfo != null
3667 ? app.instrumentationInfo.packageName
3668 : app.info.packageName);
3669 if (app.instrumentationClass != null) {
3670 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003671 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003672 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003673 + processName + " with config " + mConfiguration);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04003674 ApplicationInfo appInfo = app.instrumentationInfo != null
3675 ? app.instrumentationInfo : app.info;
Dianne Hackborn8ea5e1d2011-05-27 16:45:31 -07003676 app.compat = compatibilityInfoForPackageLocked(appInfo);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04003677 thread.bindApplication(processName, appInfo, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003678 app.instrumentationClass, app.instrumentationProfileFile,
3679 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003680 isRestrictedBackupMode || !normalMode,
Dianne Hackborn8ea5e1d2011-05-27 16:45:31 -07003681 mConfiguration, app.compat, getCommonServicesLocked(),
Svetoslav Ganov54d068e2011-03-02 12:58:40 -08003682 mCoreSettingsObserver.getCoreSettingsLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003683 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003684 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003685 } catch (Exception e) {
3686 // todo: Yikes! What should we do? For now we will try to
3687 // start another process, but that could easily get us in
3688 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08003689 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003690
3691 app.resetPackageList();
Dianne Hackborn1b64e0d2011-07-17 15:23:59 -07003692 app.unlinkDeathRecipient();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003693 startProcessLocked(app, "bind fail", processName);
3694 return false;
3695 }
3696
3697 // Remove this record from the list of starting applications.
3698 mPersistentStartingProcesses.remove(app);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003699 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
3700 "Attach application locked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003701 mProcessesOnHold.remove(app);
3702
3703 boolean badApp = false;
3704 boolean didSomething = false;
3705
3706 // See if the top visible activity is waiting to run in this process...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003707 ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07003708 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003709 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
3710 && processName.equals(hr.processName)) {
3711 try {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003712 if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003713 didSomething = true;
3714 }
3715 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003716 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003717 + hr.intent.getComponent().flattenToShortString(), e);
3718 badApp = true;
3719 }
3720 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003721 mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003722 }
3723 }
3724
3725 // Find any services that should be running in this process...
3726 if (!badApp && mPendingServices.size() > 0) {
3727 ServiceRecord sr = null;
3728 try {
3729 for (int i=0; i<mPendingServices.size(); i++) {
3730 sr = mPendingServices.get(i);
3731 if (app.info.uid != sr.appInfo.uid
3732 || !processName.equals(sr.processName)) {
3733 continue;
3734 }
3735
3736 mPendingServices.remove(i);
3737 i--;
3738 realStartServiceLocked(sr, app);
3739 didSomething = true;
3740 }
3741 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003742 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003743 + sr.shortName, e);
3744 badApp = true;
3745 }
3746 }
3747
3748 // Check if the next broadcast receiver is in this process...
3749 BroadcastRecord br = mPendingBroadcast;
3750 if (!badApp && br != null && br.curApp == app) {
3751 try {
3752 mPendingBroadcast = null;
3753 processCurBroadcastLocked(br, app);
3754 didSomething = true;
3755 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003756 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003757 + br.curComponent.flattenToShortString(), e);
3758 badApp = true;
Jeff Brown4d94a762010-09-23 11:33:28 -07003759 logBroadcastReceiverDiscardLocked(br);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003760 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
3761 br.resultExtras, br.resultAbort, true);
3762 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01003763 // We need to reset the state if we fails to start the receiver.
3764 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003765 }
3766 }
3767
Christopher Tate181fafa2009-05-14 11:12:14 -07003768 // Check whether the next backup agent is in this process...
3769 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003770 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003771 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07003772 try {
Dianne Hackborne2515ee2011-04-27 18:52:56 -04003773 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo,
3774 compatibilityInfoForPackageLocked(mBackupTarget.appInfo),
3775 mBackupTarget.backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -07003776 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003777 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07003778 e.printStackTrace();
3779 }
3780 }
3781
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003782 if (badApp) {
3783 // todo: Also need to kill application to deal with all
3784 // kinds of exceptions.
3785 handleAppDiedLocked(app, false);
3786 return false;
3787 }
3788
3789 if (!didSomething) {
3790 updateOomAdjLocked();
3791 }
3792
3793 return true;
3794 }
3795
3796 public final void attachApplication(IApplicationThread thread) {
3797 synchronized (this) {
3798 int callingPid = Binder.getCallingPid();
3799 final long origId = Binder.clearCallingIdentity();
3800 attachApplicationLocked(thread, callingPid);
3801 Binder.restoreCallingIdentity(origId);
3802 }
3803 }
3804
Dianne Hackborne88846e2009-09-30 21:34:25 -07003805 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003806 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003807 mMainStack.activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003808 Binder.restoreCallingIdentity(origId);
3809 }
3810
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003811 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003812 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003813 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003814 mWindowManager.enableScreenAfterBoot();
3815 }
3816
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003817 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003818 IntentFilter pkgFilter = new IntentFilter();
3819 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
3820 pkgFilter.addDataScheme("package");
3821 mContext.registerReceiver(new BroadcastReceiver() {
3822 @Override
3823 public void onReceive(Context context, Intent intent) {
3824 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
3825 if (pkgs != null) {
3826 for (String pkg : pkgs) {
Vairavan Srinivasan61f07652010-07-22 13:36:40 -07003827 synchronized (ActivityManagerService.this) {
3828 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
3829 setResultCode(Activity.RESULT_OK);
3830 return;
3831 }
3832 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003833 }
3834 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003835 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003836 }, pkgFilter);
3837
3838 synchronized (this) {
3839 // Ensure that any processes we had put on hold are now started
3840 // up.
3841 final int NP = mProcessesOnHold.size();
3842 if (NP > 0) {
3843 ArrayList<ProcessRecord> procs =
3844 new ArrayList<ProcessRecord>(mProcessesOnHold);
3845 for (int ip=0; ip<NP; ip++) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003846 if (DEBUG_PROCESSES) Slog.v(TAG, "Starting process on hold: "
3847 + procs.get(ip));
3848 startProcessLocked(procs.get(ip), "on-hold", null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003849 }
3850 }
3851
3852 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07003853 // Start looking for apps that are abusing wake locks.
3854 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07003855 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003856 // Tell anyone interested that we are done booting!
Dianne Hackbornf4c454b2010-08-11 12:47:41 -07003857 SystemProperties.set("sys.boot_completed", "1");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003858 broadcastIntentLocked(null, null,
3859 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
3860 null, null, 0, null, null,
3861 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
3862 false, false, MY_PID, Process.SYSTEM_UID);
3863 }
3864 }
3865 }
3866
3867 final void ensureBootCompleted() {
3868 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003869 boolean enableScreen;
3870 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003871 booting = mBooting;
3872 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003873 enableScreen = !mBooted;
3874 mBooted = true;
3875 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003876
3877 if (booting) {
3878 finishBooting();
3879 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003880
3881 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003882 enableScreenAfterBoot();
3883 }
3884 }
3885
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08003886 public final void activityPaused(IBinder token) {
3887 final long origId = Binder.clearCallingIdentity();
3888 mMainStack.activityPaused(token, false);
3889 Binder.restoreCallingIdentity(origId);
3890 }
3891
3892 public final void activityStopped(IBinder token, Bundle icicle, Bitmap thumbnail,
3893 CharSequence description) {
3894 if (localLOGV) Slog.v(
3895 TAG, "Activity stopped: token=" + token);
3896
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003897 // Refuse possible leaked file descriptors
3898 if (icicle != null && icicle.hasFileDescriptors()) {
3899 throw new IllegalArgumentException("File descriptors passed in Bundle");
3900 }
3901
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003902 ActivityRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003903
3904 final long origId = Binder.clearCallingIdentity();
3905
3906 synchronized (this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07003907 r = mMainStack.isInStackLocked(token);
3908 if (r != null) {
3909 r.stack.activityStoppedLocked(r, icicle, thumbnail, description);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003910 }
3911 }
3912
3913 if (r != null) {
3914 sendPendingThumbnail(r, null, null, null, false);
3915 }
3916
3917 trimApplications();
3918
3919 Binder.restoreCallingIdentity(origId);
3920 }
3921
3922 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003923 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003924 mMainStack.activityDestroyed(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003925 }
3926
3927 public String getCallingPackage(IBinder token) {
3928 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003929 ActivityRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07003930 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003931 }
3932 }
3933
3934 public ComponentName getCallingActivity(IBinder token) {
3935 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003936 ActivityRecord r = getCallingRecordLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003937 return r != null ? r.intent.getComponent() : null;
3938 }
3939 }
3940
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003941 private ActivityRecord getCallingRecordLocked(IBinder token) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07003942 ActivityRecord r = mMainStack.isInStackLocked(token);
3943 if (r == null) {
3944 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003945 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -07003946 return r.resultTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003947 }
3948
3949 public ComponentName getActivityClassForToken(IBinder token) {
3950 synchronized(this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07003951 ActivityRecord r = mMainStack.isInStackLocked(token);
3952 if (r == null) {
3953 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003954 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -07003955 return r.intent.getComponent();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003956 }
3957 }
3958
3959 public String getPackageForToken(IBinder token) {
3960 synchronized(this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07003961 ActivityRecord r = mMainStack.isInStackLocked(token);
3962 if (r == null) {
3963 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003964 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -07003965 return r.packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003966 }
3967 }
3968
3969 public IIntentSender getIntentSender(int type,
3970 String packageName, IBinder token, String resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003971 int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003972 // Refuse possible leaked file descriptors
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003973 if (intents != null) {
3974 if (intents.length < 1) {
3975 throw new IllegalArgumentException("Intents array length must be >= 1");
3976 }
3977 for (int i=0; i<intents.length; i++) {
3978 Intent intent = intents[i];
Dianne Hackborn52b0ce02011-04-14 13:09:32 -07003979 if (intent != null) {
3980 if (intent.hasFileDescriptors()) {
3981 throw new IllegalArgumentException("File descriptors passed in Intent");
3982 }
3983 if (type == INTENT_SENDER_BROADCAST &&
3984 (intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
3985 throw new IllegalArgumentException(
3986 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
3987 }
3988 intents[i] = new Intent(intent);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003989 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003990 }
3991 if (resolvedTypes != null && resolvedTypes.length != intents.length) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003992 throw new IllegalArgumentException(
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003993 "Intent array length does not match resolvedTypes length");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003994 }
3995 }
3996
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003997 synchronized(this) {
3998 int callingUid = Binder.getCallingUid();
3999 try {
Jeff Brown10e89712011-07-08 18:52:57 -07004000 if (callingUid != 0 && callingUid != Process.SYSTEM_UID) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004001 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004002 .getPackageUid(packageName);
4003 if (uid != Binder.getCallingUid()) {
4004 String msg = "Permission Denial: getIntentSender() from pid="
4005 + Binder.getCallingPid()
4006 + ", uid=" + Binder.getCallingUid()
4007 + ", (need uid=" + uid + ")"
4008 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004009 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004010 throw new SecurityException(msg);
4011 }
4012 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004013
4014 return getIntentSenderLocked(type, packageName, callingUid,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004015 token, resultWho, requestCode, intents, resolvedTypes, flags);
Dianne Hackborn860755f2010-06-03 18:47:52 -07004016
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004017 } catch (RemoteException e) {
4018 throw new SecurityException(e);
4019 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004020 }
4021 }
4022
4023 IIntentSender getIntentSenderLocked(int type,
4024 String packageName, int callingUid, IBinder token, String resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004025 int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004026 ActivityRecord activity = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004027 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004028 activity = mMainStack.isInStackLocked(token);
4029 if (activity == null) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07004030 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004031 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004032 if (activity.finishing) {
4033 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004034 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004035 }
4036
4037 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
4038 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
4039 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
4040 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
4041 |PendingIntent.FLAG_UPDATE_CURRENT);
4042
4043 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
4044 type, packageName, activity, resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004045 requestCode, intents, resolvedTypes, flags);
Dianne Hackborn860755f2010-06-03 18:47:52 -07004046 WeakReference<PendingIntentRecord> ref;
4047 ref = mIntentSenderRecords.get(key);
4048 PendingIntentRecord rec = ref != null ? ref.get() : null;
4049 if (rec != null) {
4050 if (!cancelCurrent) {
4051 if (updateCurrent) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004052 if (rec.key.requestIntent != null) {
4053 rec.key.requestIntent.replaceExtras(intents != null ? intents[0] : null);
4054 }
4055 if (intents != null) {
4056 intents[intents.length-1] = rec.key.requestIntent;
4057 rec.key.allIntents = intents;
4058 rec.key.allResolvedTypes = resolvedTypes;
4059 } else {
4060 rec.key.allIntents = null;
4061 rec.key.allResolvedTypes = null;
4062 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004063 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004064 return rec;
4065 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004066 rec.canceled = true;
4067 mIntentSenderRecords.remove(key);
4068 }
4069 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004070 return rec;
4071 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004072 rec = new PendingIntentRecord(this, key, callingUid);
4073 mIntentSenderRecords.put(key, rec.ref);
4074 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
4075 if (activity.pendingResults == null) {
4076 activity.pendingResults
4077 = new HashSet<WeakReference<PendingIntentRecord>>();
4078 }
4079 activity.pendingResults.add(rec.ref);
4080 }
4081 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004082 }
4083
4084 public void cancelIntentSender(IIntentSender sender) {
4085 if (!(sender instanceof PendingIntentRecord)) {
4086 return;
4087 }
4088 synchronized(this) {
4089 PendingIntentRecord rec = (PendingIntentRecord)sender;
4090 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004091 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004092 .getPackageUid(rec.key.packageName);
4093 if (uid != Binder.getCallingUid()) {
4094 String msg = "Permission Denial: cancelIntentSender() from pid="
4095 + Binder.getCallingPid()
4096 + ", uid=" + Binder.getCallingUid()
4097 + " is not allowed to cancel packges "
4098 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004099 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004100 throw new SecurityException(msg);
4101 }
4102 } catch (RemoteException e) {
4103 throw new SecurityException(e);
4104 }
4105 cancelIntentSenderLocked(rec, true);
4106 }
4107 }
4108
4109 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
4110 rec.canceled = true;
4111 mIntentSenderRecords.remove(rec.key);
4112 if (cleanActivity && rec.key.activity != null) {
4113 rec.key.activity.pendingResults.remove(rec.ref);
4114 }
4115 }
4116
4117 public String getPackageForIntentSender(IIntentSender pendingResult) {
4118 if (!(pendingResult instanceof PendingIntentRecord)) {
4119 return null;
4120 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07004121 try {
4122 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
4123 return res.key.packageName;
4124 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004125 }
4126 return null;
4127 }
4128
Dianne Hackborn6c418d52011-06-29 14:05:33 -07004129 public boolean isIntentSenderTargetedToPackage(IIntentSender pendingResult) {
4130 if (!(pendingResult instanceof PendingIntentRecord)) {
4131 return false;
4132 }
4133 try {
4134 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
4135 if (res.key.allIntents == null) {
4136 return false;
4137 }
4138 for (int i=0; i<res.key.allIntents.length; i++) {
4139 Intent intent = res.key.allIntents[i];
4140 if (intent.getPackage() != null && intent.getComponent() != null) {
4141 return false;
4142 }
4143 }
4144 return true;
4145 } catch (ClassCastException e) {
4146 }
4147 return false;
4148 }
4149
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004150 public void setProcessLimit(int max) {
4151 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4152 "setProcessLimit()");
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004153 synchronized (this) {
4154 mProcessLimit = max < 0 ? MAX_HIDDEN_APPS : max;
4155 mProcessLimitOverride = max;
4156 }
4157 trimApplications();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004158 }
4159
4160 public int getProcessLimit() {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004161 synchronized (this) {
4162 return mProcessLimitOverride;
4163 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004164 }
4165
4166 void foregroundTokenDied(ForegroundToken token) {
4167 synchronized (ActivityManagerService.this) {
4168 synchronized (mPidsSelfLocked) {
4169 ForegroundToken cur
4170 = mForegroundProcesses.get(token.pid);
4171 if (cur != token) {
4172 return;
4173 }
4174 mForegroundProcesses.remove(token.pid);
4175 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
4176 if (pr == null) {
4177 return;
4178 }
4179 pr.forcingToForeground = null;
4180 pr.foregroundServices = false;
4181 }
4182 updateOomAdjLocked();
4183 }
4184 }
4185
4186 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
4187 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4188 "setProcessForeground()");
4189 synchronized(this) {
4190 boolean changed = false;
4191
4192 synchronized (mPidsSelfLocked) {
4193 ProcessRecord pr = mPidsSelfLocked.get(pid);
4194 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004195 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004196 return;
4197 }
4198 ForegroundToken oldToken = mForegroundProcesses.get(pid);
4199 if (oldToken != null) {
4200 oldToken.token.unlinkToDeath(oldToken, 0);
4201 mForegroundProcesses.remove(pid);
4202 pr.forcingToForeground = null;
4203 changed = true;
4204 }
4205 if (isForeground && token != null) {
4206 ForegroundToken newToken = new ForegroundToken() {
4207 public void binderDied() {
4208 foregroundTokenDied(this);
4209 }
4210 };
4211 newToken.pid = pid;
4212 newToken.token = token;
4213 try {
4214 token.linkToDeath(newToken, 0);
4215 mForegroundProcesses.put(pid, newToken);
4216 pr.forcingToForeground = token;
4217 changed = true;
4218 } catch (RemoteException e) {
4219 // If the process died while doing this, we will later
4220 // do the cleanup with the process death link.
4221 }
4222 }
4223 }
4224
4225 if (changed) {
4226 updateOomAdjLocked();
4227 }
4228 }
4229 }
4230
4231 // =========================================================
4232 // PERMISSIONS
4233 // =========================================================
4234
4235 static class PermissionController extends IPermissionController.Stub {
4236 ActivityManagerService mActivityManagerService;
4237 PermissionController(ActivityManagerService activityManagerService) {
4238 mActivityManagerService = activityManagerService;
4239 }
4240
4241 public boolean checkPermission(String permission, int pid, int uid) {
4242 return mActivityManagerService.checkPermission(permission, pid,
4243 uid) == PackageManager.PERMISSION_GRANTED;
4244 }
4245 }
4246
4247 /**
4248 * This can be called with or without the global lock held.
4249 */
4250 int checkComponentPermission(String permission, int pid, int uid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004251 int owningUid, boolean exported) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004252 // We might be performing an operation on behalf of an indirect binder
4253 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
4254 // client identity accordingly before proceeding.
4255 Identity tlsIdentity = sCallerIdentity.get();
4256 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004257 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004258 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
4259 uid = tlsIdentity.uid;
4260 pid = tlsIdentity.pid;
4261 }
4262
4263 // Root, system server and our own process get to do everything.
Jeff Brown10e89712011-07-08 18:52:57 -07004264 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004265 return PackageManager.PERMISSION_GRANTED;
4266 }
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004267 // If there is a uid that owns whatever is being accessed, it has
4268 // blanket access to it regardless of the permissions it requires.
4269 if (owningUid >= 0 && uid == owningUid) {
4270 return PackageManager.PERMISSION_GRANTED;
4271 }
4272 // If the target is not exported, then nobody else can get to it.
4273 if (!exported) {
4274 Slog.w(TAG, "Permission denied: checkComponentPermission() owningUid=" + owningUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004275 return PackageManager.PERMISSION_DENIED;
4276 }
4277 if (permission == null) {
4278 return PackageManager.PERMISSION_GRANTED;
4279 }
4280 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004281 return AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004282 .checkUidPermission(permission, uid);
4283 } catch (RemoteException e) {
4284 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004285 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004286 }
4287 return PackageManager.PERMISSION_DENIED;
4288 }
4289
4290 /**
4291 * As the only public entry point for permissions checking, this method
4292 * can enforce the semantic that requesting a check on a null global
4293 * permission is automatically denied. (Internally a null permission
4294 * string is used when calling {@link #checkComponentPermission} in cases
4295 * when only uid-based security is needed.)
4296 *
4297 * This can be called with or without the global lock held.
4298 */
4299 public int checkPermission(String permission, int pid, int uid) {
4300 if (permission == null) {
4301 return PackageManager.PERMISSION_DENIED;
4302 }
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004303 return checkComponentPermission(permission, pid, uid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004304 }
4305
4306 /**
4307 * Binder IPC calls go through the public entry point.
4308 * This can be called with or without the global lock held.
4309 */
4310 int checkCallingPermission(String permission) {
4311 return checkPermission(permission,
4312 Binder.getCallingPid(),
4313 Binder.getCallingUid());
4314 }
4315
4316 /**
4317 * This can be called with or without the global lock held.
4318 */
4319 void enforceCallingPermission(String permission, String func) {
4320 if (checkCallingPermission(permission)
4321 == PackageManager.PERMISSION_GRANTED) {
4322 return;
4323 }
4324
4325 String msg = "Permission Denial: " + func + " from pid="
4326 + Binder.getCallingPid()
4327 + ", uid=" + Binder.getCallingUid()
4328 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004329 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004330 throw new SecurityException(msg);
4331 }
4332
4333 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
Dianne Hackborn48058e82010-09-27 16:53:23 -07004334 ProviderInfo pi, Uri uri, int uid, int modeFlags) {
4335 boolean readPerm = (modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0;
4336 boolean writePerm = (modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0;
4337 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4338 "checkHoldingPermissionsLocked: uri=" + uri + " uid=" + uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004339 try {
Dianne Hackborn48058e82010-09-27 16:53:23 -07004340 // Is the component private from the target uid?
4341 final boolean prv = !pi.exported && pi.applicationInfo.uid != uid;
4342
4343 // Acceptable if the there is no read permission needed from the
4344 // target or the target is holding the read permission.
4345 if (!readPerm) {
4346 if ((!prv && pi.readPermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004347 (pm.checkUidPermission(pi.readPermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004348 == PackageManager.PERMISSION_GRANTED)) {
4349 readPerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004350 }
4351 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004352
4353 // Acceptable if the there is no write permission needed from the
4354 // target or the target is holding the read permission.
4355 if (!writePerm) {
4356 if (!prv && (pi.writePermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004357 (pm.checkUidPermission(pi.writePermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004358 == PackageManager.PERMISSION_GRANTED)) {
4359 writePerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004360 }
4361 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004362
4363 // Acceptable if there is a path permission matching the URI that
4364 // the target holds the permission on.
4365 PathPermission[] pps = pi.pathPermissions;
4366 if (pps != null && (!readPerm || !writePerm)) {
4367 final String path = uri.getPath();
4368 int i = pps.length;
4369 while (i > 0 && (!readPerm || !writePerm)) {
4370 i--;
4371 PathPermission pp = pps[i];
4372 if (!readPerm) {
4373 final String pprperm = pp.getReadPermission();
4374 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking read perm for "
4375 + pprperm + " for " + pp.getPath()
4376 + ": match=" + pp.match(path)
4377 + " check=" + pm.checkUidPermission(pprperm, uid));
4378 if (pprperm != null && pp.match(path) &&
4379 (pm.checkUidPermission(pprperm, uid)
4380 == PackageManager.PERMISSION_GRANTED)) {
4381 readPerm = true;
4382 }
4383 }
4384 if (!writePerm) {
4385 final String ppwperm = pp.getWritePermission();
4386 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking write perm "
4387 + ppwperm + " for " + pp.getPath()
4388 + ": match=" + pp.match(path)
4389 + " check=" + pm.checkUidPermission(ppwperm, uid));
4390 if (ppwperm != null && pp.match(path) &&
4391 (pm.checkUidPermission(ppwperm, uid)
4392 == PackageManager.PERMISSION_GRANTED)) {
4393 writePerm = true;
4394 }
4395 }
4396 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004397 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004398 } catch (RemoteException e) {
4399 return false;
4400 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004401
4402 return readPerm && writePerm;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004403 }
4404
4405 private final boolean checkUriPermissionLocked(Uri uri, int uid,
4406 int modeFlags) {
4407 // Root gets to do everything.
Jeff Brown10e89712011-07-08 18:52:57 -07004408 if (uid == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004409 return true;
4410 }
4411 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
4412 if (perms == null) return false;
4413 UriPermission perm = perms.get(uri);
4414 if (perm == null) return false;
4415 return (modeFlags&perm.modeFlags) == modeFlags;
4416 }
4417
4418 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
4419 // Another redirected-binder-call permissions check as in
4420 // {@link checkComponentPermission}.
4421 Identity tlsIdentity = sCallerIdentity.get();
4422 if (tlsIdentity != null) {
4423 uid = tlsIdentity.uid;
4424 pid = tlsIdentity.pid;
4425 }
4426
4427 // Our own process gets to do everything.
4428 if (pid == MY_PID) {
4429 return PackageManager.PERMISSION_GRANTED;
4430 }
4431 synchronized(this) {
4432 return checkUriPermissionLocked(uri, uid, modeFlags)
4433 ? PackageManager.PERMISSION_GRANTED
4434 : PackageManager.PERMISSION_DENIED;
4435 }
4436 }
4437
Dianne Hackborn39792d22010-08-19 18:01:52 -07004438 /**
4439 * Check if the targetPkg can be granted permission to access uri by
4440 * the callingUid using the given modeFlags. Throws a security exception
4441 * if callingUid is not allowed to do this. Returns the uid of the target
4442 * if the URI permission grant should be performed; returns -1 if it is not
4443 * needed (for example targetPkg already has permission to access the URI).
4444 */
4445 int checkGrantUriPermissionLocked(int callingUid, String targetPkg,
4446 Uri uri, int modeFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004447 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4448 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4449 if (modeFlags == 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004450 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004451 }
4452
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004453 if (targetPkg != null) {
4454 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4455 "Checking grant " + targetPkg + " permission to " + uri);
4456 }
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004457
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004458 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004459
4460 // If this is not a content: uri, we can't do anything with it.
4461 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004462 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004463 "Can't grant URI permission for non-content URI: " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004464 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004465 }
4466
4467 String name = uri.getAuthority();
4468 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004469 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004470 if (cpr != null) {
4471 pi = cpr.info;
4472 } else {
4473 try {
4474 pi = pm.resolveContentProvider(name,
4475 PackageManager.GET_URI_PERMISSION_PATTERNS);
4476 } catch (RemoteException ex) {
4477 }
4478 }
4479 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004480 Slog.w(TAG, "No content provider found for: " + name);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004481 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004482 }
4483
4484 int targetUid;
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004485 if (targetPkg != null) {
4486 try {
4487 targetUid = pm.getPackageUid(targetPkg);
4488 if (targetUid < 0) {
4489 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4490 "Can't grant URI permission no uid for: " + targetPkg);
4491 return -1;
4492 }
4493 } catch (RemoteException ex) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004494 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004495 }
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004496 } else {
4497 targetUid = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004498 }
4499
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004500 if (targetUid >= 0) {
4501 // First... does the target actually need this permission?
4502 if (checkHoldingPermissionsLocked(pm, pi, uri, targetUid, modeFlags)) {
4503 // No need to grant the target this permission.
4504 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4505 "Target " + targetPkg + " already has full permission to " + uri);
4506 return -1;
4507 }
4508 } else {
4509 // First... there is no target package, so can anyone access it?
4510 boolean allowed = pi.exported;
4511 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4512 if (pi.readPermission != null) {
4513 allowed = false;
4514 }
4515 }
4516 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4517 if (pi.writePermission != null) {
4518 allowed = false;
4519 }
4520 }
4521 if (allowed) {
4522 return -1;
4523 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004524 }
4525
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004526 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004527 if (!pi.grantUriPermissions) {
4528 throw new SecurityException("Provider " + pi.packageName
4529 + "/" + pi.name
4530 + " does not allow granting of Uri permissions (uri "
4531 + uri + ")");
4532 }
4533 if (pi.uriPermissionPatterns != null) {
4534 final int N = pi.uriPermissionPatterns.length;
4535 boolean allowed = false;
4536 for (int i=0; i<N; i++) {
4537 if (pi.uriPermissionPatterns[i] != null
4538 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
4539 allowed = true;
4540 break;
4541 }
4542 }
4543 if (!allowed) {
4544 throw new SecurityException("Provider " + pi.packageName
4545 + "/" + pi.name
4546 + " does not allow granting of permission to path of Uri "
4547 + uri);
4548 }
4549 }
4550
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004551 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004552 // this uri?
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004553 if (callingUid != Process.myUid()) {
4554 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
4555 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4556 throw new SecurityException("Uid " + callingUid
4557 + " does not have permission to uri " + uri);
4558 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004559 }
4560 }
4561
Dianne Hackborn39792d22010-08-19 18:01:52 -07004562 return targetUid;
4563 }
4564
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004565 public int checkGrantUriPermission(int callingUid, String targetPkg,
4566 Uri uri, int modeFlags) {
4567 synchronized(this) {
4568 return checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4569 }
4570 }
4571
Dianne Hackborn39792d22010-08-19 18:01:52 -07004572 void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg,
4573 Uri uri, int modeFlags, UriPermissionOwner owner) {
4574 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4575 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4576 if (modeFlags == 0) {
4577 return;
4578 }
4579
4580 // So here we are: the caller has the assumed permission
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004581 // to the uri, and the target doesn't. Let's now give this to
4582 // the target.
4583
Joe Onorato8a9b2202010-02-26 18:56:32 -08004584 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004585 "Granting " + targetPkg + "/" + targetUid + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004586
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004587 HashMap<Uri, UriPermission> targetUris
4588 = mGrantedUriPermissions.get(targetUid);
4589 if (targetUris == null) {
4590 targetUris = new HashMap<Uri, UriPermission>();
4591 mGrantedUriPermissions.put(targetUid, targetUris);
4592 }
4593
4594 UriPermission perm = targetUris.get(uri);
4595 if (perm == null) {
4596 perm = new UriPermission(targetUid, uri);
4597 targetUris.put(uri, perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004598 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004599
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004600 perm.modeFlags |= modeFlags;
Dianne Hackborn39792d22010-08-19 18:01:52 -07004601 if (owner == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004602 perm.globalModeFlags |= modeFlags;
Vairavan Srinivasan91c12c22011-01-21 18:26:06 -08004603 } else {
4604 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4605 perm.readOwners.add(owner);
4606 owner.addReadPermission(perm);
4607 }
4608 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4609 perm.writeOwners.add(owner);
4610 owner.addWritePermission(perm);
4611 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004612 }
4613 }
4614
Dianne Hackborn39792d22010-08-19 18:01:52 -07004615 void grantUriPermissionLocked(int callingUid,
4616 String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) {
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004617 if (targetPkg == null) {
4618 throw new NullPointerException("targetPkg");
4619 }
4620
Dianne Hackborn39792d22010-08-19 18:01:52 -07004621 int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4622 if (targetUid < 0) {
4623 return;
4624 }
4625
4626 grantUriPermissionUncheckedLocked(targetUid, targetPkg, uri, modeFlags, owner);
4627 }
4628
4629 /**
4630 * Like checkGrantUriPermissionLocked, but takes an Intent.
4631 */
4632 int checkGrantUriPermissionFromIntentLocked(int callingUid,
4633 String targetPkg, Intent intent) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07004634 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004635 "Checking URI perm to " + (intent != null ? intent.getData() : null)
Dianne Hackbornb424b632010-08-18 15:59:05 -07004636 + " from " + intent + "; flags=0x"
4637 + Integer.toHexString(intent != null ? intent.getFlags() : 0));
4638
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004639 if (targetPkg == null) {
4640 throw new NullPointerException("targetPkg");
4641 }
4642
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004643 if (intent == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004644 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004645 }
4646 Uri data = intent.getData();
4647 if (data == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004648 return -1;
4649 }
4650 return checkGrantUriPermissionLocked(callingUid, targetPkg, data,
4651 intent.getFlags());
4652 }
4653
4654 /**
4655 * Like grantUriPermissionUncheckedLocked, but takes an Intent.
4656 */
4657 void grantUriPermissionUncheckedFromIntentLocked(int targetUid,
4658 String targetPkg, Intent intent, UriPermissionOwner owner) {
4659 grantUriPermissionUncheckedLocked(targetUid, targetPkg, intent.getData(),
4660 intent.getFlags(), owner);
4661 }
4662
4663 void grantUriPermissionFromIntentLocked(int callingUid,
4664 String targetPkg, Intent intent, UriPermissionOwner owner) {
4665 int targetUid = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg, intent);
4666 if (targetUid < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004667 return;
4668 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07004669
4670 grantUriPermissionUncheckedFromIntentLocked(targetUid, targetPkg, intent, owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004671 }
4672
4673 public void grantUriPermission(IApplicationThread caller, String targetPkg,
4674 Uri uri, int modeFlags) {
4675 synchronized(this) {
4676 final ProcessRecord r = getRecordForAppLocked(caller);
4677 if (r == null) {
4678 throw new SecurityException("Unable to find app for caller "
4679 + caller
4680 + " when granting permission to uri " + uri);
4681 }
4682 if (targetPkg == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004683 throw new IllegalArgumentException("null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004684 }
4685 if (uri == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004686 throw new IllegalArgumentException("null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004687 }
4688
4689 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
4690 null);
4691 }
4692 }
4693
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004694 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004695 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
4696 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
4697 HashMap<Uri, UriPermission> perms
4698 = mGrantedUriPermissions.get(perm.uid);
4699 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004700 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004701 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004702 perms.remove(perm.uri);
4703 if (perms.size() == 0) {
4704 mGrantedUriPermissions.remove(perm.uid);
4705 }
4706 }
4707 }
4708 }
4709
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004710 private void revokeUriPermissionLocked(int callingUid, Uri uri,
4711 int modeFlags) {
4712 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4713 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4714 if (modeFlags == 0) {
4715 return;
4716 }
4717
Joe Onorato8a9b2202010-02-26 18:56:32 -08004718 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004719 "Revoking all granted permissions to " + uri);
4720
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004721 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004722
4723 final String authority = uri.getAuthority();
4724 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004725 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004726 if (cpr != null) {
4727 pi = cpr.info;
4728 } else {
4729 try {
4730 pi = pm.resolveContentProvider(authority,
4731 PackageManager.GET_URI_PERMISSION_PATTERNS);
4732 } catch (RemoteException ex) {
4733 }
4734 }
4735 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004736 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004737 return;
4738 }
4739
4740 // Does the caller have this permission on the URI?
Dianne Hackborn48058e82010-09-27 16:53:23 -07004741 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004742 // Right now, if you are not the original owner of the permission,
4743 // you are not allowed to revoke it.
4744 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4745 throw new SecurityException("Uid " + callingUid
4746 + " does not have permission to uri " + uri);
4747 //}
4748 }
4749
4750 // Go through all of the permissions and remove any that match.
4751 final List<String> SEGMENTS = uri.getPathSegments();
4752 if (SEGMENTS != null) {
4753 final int NS = SEGMENTS.size();
4754 int N = mGrantedUriPermissions.size();
4755 for (int i=0; i<N; i++) {
4756 HashMap<Uri, UriPermission> perms
4757 = mGrantedUriPermissions.valueAt(i);
4758 Iterator<UriPermission> it = perms.values().iterator();
4759 toploop:
4760 while (it.hasNext()) {
4761 UriPermission perm = it.next();
4762 Uri targetUri = perm.uri;
4763 if (!authority.equals(targetUri.getAuthority())) {
4764 continue;
4765 }
4766 List<String> targetSegments = targetUri.getPathSegments();
4767 if (targetSegments == null) {
4768 continue;
4769 }
4770 if (targetSegments.size() < NS) {
4771 continue;
4772 }
4773 for (int j=0; j<NS; j++) {
4774 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
4775 continue toploop;
4776 }
4777 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004778 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004779 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004780 perm.clearModes(modeFlags);
4781 if (perm.modeFlags == 0) {
4782 it.remove();
4783 }
4784 }
4785 if (perms.size() == 0) {
4786 mGrantedUriPermissions.remove(
4787 mGrantedUriPermissions.keyAt(i));
4788 N--;
4789 i--;
4790 }
4791 }
4792 }
4793 }
4794
4795 public void revokeUriPermission(IApplicationThread caller, Uri uri,
4796 int modeFlags) {
4797 synchronized(this) {
4798 final ProcessRecord r = getRecordForAppLocked(caller);
4799 if (r == null) {
4800 throw new SecurityException("Unable to find app for caller "
4801 + caller
4802 + " when revoking permission to uri " + uri);
4803 }
4804 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004805 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004806 return;
4807 }
4808
4809 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4810 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4811 if (modeFlags == 0) {
4812 return;
4813 }
4814
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004815 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004816
4817 final String authority = uri.getAuthority();
4818 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004819 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004820 if (cpr != null) {
4821 pi = cpr.info;
4822 } else {
4823 try {
4824 pi = pm.resolveContentProvider(authority,
4825 PackageManager.GET_URI_PERMISSION_PATTERNS);
4826 } catch (RemoteException ex) {
4827 }
4828 }
4829 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004830 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004831 return;
4832 }
4833
4834 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
4835 }
4836 }
4837
Dianne Hackborn7e269642010-08-25 19:50:20 -07004838 @Override
4839 public IBinder newUriPermissionOwner(String name) {
4840 synchronized(this) {
4841 UriPermissionOwner owner = new UriPermissionOwner(this, name);
4842 return owner.getExternalTokenLocked();
4843 }
4844 }
4845
4846 @Override
4847 public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg,
4848 Uri uri, int modeFlags) {
4849 synchronized(this) {
4850 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4851 if (owner == null) {
4852 throw new IllegalArgumentException("Unknown owner: " + token);
4853 }
4854 if (fromUid != Binder.getCallingUid()) {
4855 if (Binder.getCallingUid() != Process.myUid()) {
4856 // Only system code can grant URI permissions on behalf
4857 // of other users.
4858 throw new SecurityException("nice try");
4859 }
4860 }
4861 if (targetPkg == null) {
4862 throw new IllegalArgumentException("null target");
4863 }
4864 if (uri == null) {
4865 throw new IllegalArgumentException("null uri");
4866 }
4867
4868 grantUriPermissionLocked(fromUid, targetPkg, uri, modeFlags, owner);
4869 }
4870 }
4871
4872 @Override
4873 public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode) {
4874 synchronized(this) {
4875 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4876 if (owner == null) {
4877 throw new IllegalArgumentException("Unknown owner: " + token);
4878 }
4879
4880 if (uri == null) {
4881 owner.removeUriPermissionsLocked(mode);
4882 } else {
4883 owner.removeUriPermissionLocked(uri, mode);
4884 }
4885 }
4886 }
4887
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004888 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
4889 synchronized (this) {
4890 ProcessRecord app =
4891 who != null ? getRecordForAppLocked(who) : null;
4892 if (app == null) return;
4893
4894 Message msg = Message.obtain();
4895 msg.what = WAIT_FOR_DEBUGGER_MSG;
4896 msg.obj = app;
4897 msg.arg1 = waiting ? 1 : 0;
4898 mHandler.sendMessage(msg);
4899 }
4900 }
4901
4902 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
4903 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08004904 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004905 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08004906 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004907 }
4908
4909 // =========================================================
4910 // TASK MANAGEMENT
4911 // =========================================================
4912
4913 public List getTasks(int maxNum, int flags,
4914 IThumbnailReceiver receiver) {
4915 ArrayList list = new ArrayList();
4916
4917 PendingThumbnailsRecord pending = null;
4918 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004919 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004920
4921 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004922 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004923 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
4924 + ", receiver=" + receiver);
4925
4926 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
4927 != PackageManager.PERMISSION_GRANTED) {
4928 if (receiver != null) {
4929 // If the caller wants to wait for pending thumbnails,
4930 // it ain't gonna get them.
4931 try {
4932 receiver.finished();
4933 } catch (RemoteException ex) {
4934 }
4935 }
4936 String msg = "Permission Denial: getTasks() from pid="
4937 + Binder.getCallingPid()
4938 + ", uid=" + Binder.getCallingUid()
4939 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004940 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004941 throw new SecurityException(msg);
4942 }
4943
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004944 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004945 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004946 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004947 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004948 TaskRecord curTask = null;
4949 int numActivities = 0;
4950 int numRunning = 0;
4951 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004952 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004953 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004954 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004955
4956 // Initialize state for next task if needed.
4957 if (top == null ||
4958 (top.state == ActivityState.INITIALIZING
4959 && top.task == r.task)) {
4960 top = r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004961 curTask = r.task;
4962 numActivities = numRunning = 0;
4963 }
4964
4965 // Add 'r' into the current task.
4966 numActivities++;
4967 if (r.app != null && r.app.thread != null) {
4968 numRunning++;
4969 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004970
Joe Onorato8a9b2202010-02-26 18:56:32 -08004971 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004972 TAG, r.intent.getComponent().flattenToShortString()
4973 + ": task=" + r.task);
4974
4975 // If the next one is a different task, generate a new
4976 // TaskInfo entry for what we have.
4977 if (next == null || next.task != curTask) {
4978 ActivityManager.RunningTaskInfo ci
4979 = new ActivityManager.RunningTaskInfo();
4980 ci.id = curTask.taskId;
4981 ci.baseActivity = r.intent.getComponent();
4982 ci.topActivity = top.intent.getComponent();
Dianne Hackbornf26fd992011-04-08 18:14:09 -07004983 if (top.thumbHolder != null) {
4984 ci.description = top.thumbHolder.lastDescription;
4985 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004986 ci.numActivities = numActivities;
4987 ci.numRunning = numRunning;
4988 //System.out.println(
4989 // "#" + maxNum + ": " + " descr=" + ci.description);
4990 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004991 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004992 TAG, "State=" + top.state + "Idle=" + top.idle
4993 + " app=" + top.app
4994 + " thr=" + (top.app != null ? top.app.thread : null));
4995 if (top.state == ActivityState.RESUMED
4996 || top.state == ActivityState.PAUSING) {
4997 if (top.idle && top.app != null
4998 && top.app.thread != null) {
4999 topRecord = top;
5000 topThumbnail = top.app.thread;
5001 } else {
5002 top.thumbnailNeeded = true;
5003 }
5004 }
5005 if (pending == null) {
5006 pending = new PendingThumbnailsRecord(receiver);
5007 }
5008 pending.pendingRecords.add(top);
5009 }
5010 list.add(ci);
5011 maxNum--;
5012 top = null;
5013 }
5014 }
5015
5016 if (pending != null) {
5017 mPendingThumbnails.add(pending);
5018 }
5019 }
5020
Joe Onorato8a9b2202010-02-26 18:56:32 -08005021 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005022
5023 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005024 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005025 try {
5026 topThumbnail.requestThumbnail(topRecord);
5027 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005028 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005029 sendPendingThumbnail(null, topRecord, null, null, true);
5030 }
5031 }
5032
5033 if (pending == null && receiver != null) {
5034 // In this case all thumbnails were available and the client
5035 // is being asked to be told when the remaining ones come in...
5036 // which is unusually, since the top-most currently running
5037 // activity should never have a canned thumbnail! Oh well.
5038 try {
5039 receiver.finished();
5040 } catch (RemoteException ex) {
5041 }
5042 }
5043
5044 return list;
5045 }
5046
5047 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
5048 int flags) {
5049 synchronized (this) {
5050 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
5051 "getRecentTasks()");
5052
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005053 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07005054
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005055 final int N = mRecentTasks.size();
5056 ArrayList<ActivityManager.RecentTaskInfo> res
5057 = new ArrayList<ActivityManager.RecentTaskInfo>(
5058 maxNum < N ? maxNum : N);
5059 for (int i=0; i<N && maxNum > 0; i++) {
5060 TaskRecord tr = mRecentTasks.get(i);
5061 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
5062 || (tr.intent == null)
5063 || ((tr.intent.getFlags()
5064 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
5065 ActivityManager.RecentTaskInfo rti
5066 = new ActivityManager.RecentTaskInfo();
5067 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
Dianne Hackbornd94df452011-02-16 18:53:31 -08005068 rti.persistentId = tr.taskId;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005069 rti.baseIntent = new Intent(
5070 tr.intent != null ? tr.intent : tr.affinityIntent);
5071 rti.origActivity = tr.origActivity;
Dianne Hackbornd2835932010-12-13 16:28:46 -08005072 rti.description = tr.lastDescription;
5073
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07005074 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
5075 // Check whether this activity is currently available.
5076 try {
5077 if (rti.origActivity != null) {
5078 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
5079 continue;
5080 }
5081 } else if (rti.baseIntent != null) {
5082 if (pm.queryIntentActivities(rti.baseIntent,
5083 null, 0) == null) {
5084 continue;
5085 }
5086 }
5087 } catch (RemoteException e) {
5088 // Will never happen.
5089 }
5090 }
5091
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005092 res.add(rti);
5093 maxNum--;
5094 }
5095 }
5096 return res;
5097 }
5098 }
5099
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005100 private TaskRecord taskForIdLocked(int id) {
5101 final int N = mRecentTasks.size();
5102 for (int i=0; i<N; i++) {
5103 TaskRecord tr = mRecentTasks.get(i);
5104 if (tr.taskId == id) {
5105 return tr;
Dianne Hackbornd94df452011-02-16 18:53:31 -08005106 }
5107 }
5108 return null;
5109 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005110
5111 public ActivityManager.TaskThumbnails getTaskThumbnails(int id) {
5112 synchronized (this) {
5113 enforceCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER,
5114 "getTaskThumbnails()");
5115 TaskRecord tr = taskForIdLocked(id);
5116 if (tr != null) {
5117 return mMainStack.getTaskThumbnailsLocked(tr);
5118 }
5119 }
5120 return null;
5121 }
5122
5123 public boolean removeSubTask(int taskId, int subTaskIndex) {
5124 synchronized (this) {
5125 enforceCallingPermission(android.Manifest.permission.REMOVE_TASKS,
5126 "removeSubTask()");
5127 long ident = Binder.clearCallingIdentity();
5128 try {
5129 return mMainStack.removeTaskActivitiesLocked(taskId, subTaskIndex) != null;
5130 } finally {
5131 Binder.restoreCallingIdentity(ident);
5132 }
5133 }
5134 }
5135
Dianne Hackborn8894cc52011-07-01 16:28:17 -07005136 private void cleanUpRemovedTaskLocked(ActivityRecord root, boolean killProcesses) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005137 TaskRecord tr = root.task;
5138 Intent baseIntent = new Intent(
5139 tr.intent != null ? tr.intent : tr.affinityIntent);
5140 ComponentName component = baseIntent.getComponent();
5141 if (component == null) {
5142 Slog.w(TAG, "Now component for base intent of task: " + tr);
5143 return;
5144 }
5145
5146 // Find any running services associated with this app.
5147 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
5148 for (ServiceRecord sr : mServices.values()) {
5149 if (sr.packageName.equals(component.getPackageName())) {
5150 services.add(sr);
5151 }
5152 }
5153
5154 // Take care of any running services associated with the app.
5155 for (int i=0; i<services.size(); i++) {
5156 ServiceRecord sr = services.get(i);
5157 if (sr.startRequested) {
5158 if ((sr.serviceInfo.flags&ServiceInfo.FLAG_STOP_WITH_TASK) != 0) {
Dianne Hackborn8894cc52011-07-01 16:28:17 -07005159 Slog.i(TAG, "Stopping service " + sr.shortName + ": remove task");
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005160 stopServiceLocked(sr);
5161 } else {
5162 sr.pendingStarts.add(new ServiceRecord.StartItem(sr, true,
5163 sr.makeNextStartId(), baseIntent, -1));
5164 if (sr.app != null && sr.app.thread != null) {
5165 sendServiceArgsLocked(sr, false);
5166 }
5167 }
5168 }
5169 }
5170
Dianne Hackborn8894cc52011-07-01 16:28:17 -07005171 if (killProcesses) {
5172 // Find any running processes associated with this app.
5173 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
5174 SparseArray<ProcessRecord> appProcs
5175 = mProcessNames.getMap().get(component.getPackageName());
5176 if (appProcs != null) {
5177 for (int i=0; i<appProcs.size(); i++) {
5178 procs.add(appProcs.valueAt(i));
5179 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005180 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005181
Dianne Hackborn8894cc52011-07-01 16:28:17 -07005182 // Kill the running processes.
5183 for (int i=0; i<procs.size(); i++) {
5184 ProcessRecord pr = procs.get(i);
5185 if (pr.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {
5186 Slog.i(TAG, "Killing " + pr.toShortString() + ": remove task");
5187 EventLog.writeEvent(EventLogTags.AM_KILL, pr.pid,
5188 pr.processName, pr.setAdj, "remove task");
5189 Process.killProcessQuiet(pr.pid);
5190 } else {
5191 pr.waitingToKill = "remove task";
5192 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005193 }
5194 }
5195 }
5196
5197 public boolean removeTask(int taskId, int flags) {
5198 synchronized (this) {
5199 enforceCallingPermission(android.Manifest.permission.REMOVE_TASKS,
5200 "removeTask()");
5201 long ident = Binder.clearCallingIdentity();
5202 try {
5203 ActivityRecord r = mMainStack.removeTaskActivitiesLocked(taskId, -1);
5204 if (r != null) {
5205 mRecentTasks.remove(r.task);
Dianne Hackborn8894cc52011-07-01 16:28:17 -07005206 cleanUpRemovedTaskLocked(r,
5207 (flags&ActivityManager.REMOVE_TASK_KILL_PROCESS) != 0);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005208 return true;
5209 }
5210 } finally {
5211 Binder.restoreCallingIdentity(ident);
5212 }
5213 }
5214 return false;
5215 }
Dianne Hackbornd94df452011-02-16 18:53:31 -08005216
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005217 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
5218 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005219 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005220 TaskRecord jt = startTask;
5221
5222 // First look backwards
5223 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005224 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005225 if (r.task != jt) {
5226 jt = r.task;
5227 if (affinity.equals(jt.affinity)) {
5228 return j;
5229 }
5230 }
5231 }
5232
5233 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005234 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005235 jt = startTask;
5236 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005237 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005238 if (r.task != jt) {
5239 if (affinity.equals(jt.affinity)) {
5240 return j;
5241 }
5242 jt = r.task;
5243 }
5244 }
5245
5246 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005247 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005248 return N-1;
5249 }
5250
5251 return -1;
5252 }
5253
5254 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005255 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005256 */
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005257 public void moveTaskToFront(int task, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005258 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5259 "moveTaskToFront()");
5260
5261 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005262 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5263 Binder.getCallingUid(), "Task to front")) {
5264 return;
5265 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005266 final long origId = Binder.clearCallingIdentity();
5267 try {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005268 TaskRecord tr = taskForIdLocked(task);
5269 if (tr != null) {
5270 if ((flags&ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
5271 mMainStack.mUserLeaving = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005272 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005273 if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
5274 // Caller wants the home activity moved with it. To accomplish this,
5275 // we'll just move the home task to the top first.
5276 mMainStack.moveHomeToFrontLocked();
5277 }
5278 mMainStack.moveTaskToFrontLocked(tr, null);
5279 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005280 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005281 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
5282 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005283 if (hr.task.taskId == task) {
Dianne Hackbornd94df452011-02-16 18:53:31 -08005284 if ((flags&ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
5285 mMainStack.mUserLeaving = true;
5286 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005287 if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
5288 // Caller wants the home activity moved with it. To accomplish this,
5289 // we'll just move the home task to the top first.
5290 mMainStack.moveHomeToFrontLocked();
5291 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005292 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005293 return;
5294 }
5295 }
5296 } finally {
5297 Binder.restoreCallingIdentity(origId);
5298 }
5299 }
5300 }
5301
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005302 public void moveTaskToBack(int task) {
5303 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5304 "moveTaskToBack()");
5305
5306 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005307 if (mMainStack.mResumedActivity != null
5308 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005309 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5310 Binder.getCallingUid(), "Task to back")) {
5311 return;
5312 }
5313 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005314 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005315 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005316 Binder.restoreCallingIdentity(origId);
5317 }
5318 }
5319
5320 /**
5321 * Moves an activity, and all of the other activities within the same task, to the bottom
5322 * of the history stack. The activity's order within the task is unchanged.
5323 *
5324 * @param token A reference to the activity we wish to move
5325 * @param nonRoot If false then this only works if the activity is the root
5326 * of a task; if true it will work for any activity in a task.
5327 * @return Returns true if the move completed, false if not.
5328 */
5329 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
5330 synchronized(this) {
5331 final long origId = Binder.clearCallingIdentity();
5332 int taskId = getTaskForActivityLocked(token, !nonRoot);
5333 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005334 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005335 }
5336 Binder.restoreCallingIdentity(origId);
5337 }
5338 return false;
5339 }
5340
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005341 public void moveTaskBackwards(int task) {
5342 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5343 "moveTaskBackwards()");
5344
5345 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005346 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5347 Binder.getCallingUid(), "Task backwards")) {
5348 return;
5349 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005350 final long origId = Binder.clearCallingIdentity();
5351 moveTaskBackwardsLocked(task);
5352 Binder.restoreCallingIdentity(origId);
5353 }
5354 }
5355
5356 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005357 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005358 }
5359
5360 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
5361 synchronized(this) {
5362 return getTaskForActivityLocked(token, onlyRoot);
5363 }
5364 }
5365
5366 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005367 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005368 TaskRecord lastTask = null;
5369 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005370 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005371 if (r == token) {
5372 if (!onlyRoot || lastTask != r.task) {
5373 return r.task.taskId;
5374 }
5375 return -1;
5376 }
5377 lastTask = r.task;
5378 }
5379
5380 return -1;
5381 }
5382
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005383 public void finishOtherInstances(IBinder token, ComponentName className) {
5384 synchronized(this) {
5385 final long origId = Binder.clearCallingIdentity();
5386
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005387 int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005388 TaskRecord lastTask = null;
5389 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005390 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005391 if (r.realActivity.equals(className)
5392 && r != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005393 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005394 null, "others")) {
5395 i--;
5396 N--;
5397 }
5398 }
5399 lastTask = r.task;
5400 }
5401
5402 Binder.restoreCallingIdentity(origId);
5403 }
5404 }
5405
5406 // =========================================================
5407 // THUMBNAILS
5408 // =========================================================
5409
5410 public void reportThumbnail(IBinder token,
5411 Bitmap thumbnail, CharSequence description) {
5412 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
5413 final long origId = Binder.clearCallingIdentity();
5414 sendPendingThumbnail(null, token, thumbnail, description, true);
5415 Binder.restoreCallingIdentity(origId);
5416 }
5417
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005418 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005419 Bitmap thumbnail, CharSequence description, boolean always) {
5420 TaskRecord task = null;
5421 ArrayList receivers = null;
5422
5423 //System.out.println("Send pending thumbnail: " + r);
5424
5425 synchronized(this) {
5426 if (r == null) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07005427 r = mMainStack.isInStackLocked(token);
5428 if (r == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005429 return;
5430 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005431 }
Dianne Hackbornf26fd992011-04-08 18:14:09 -07005432 if (thumbnail == null && r.thumbHolder != null) {
5433 thumbnail = r.thumbHolder.lastThumbnail;
5434 description = r.thumbHolder.lastDescription;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005435 }
5436 if (thumbnail == null && !always) {
5437 // If there is no thumbnail, and this entry is not actually
5438 // going away, then abort for now and pick up the next
5439 // thumbnail we get.
5440 return;
5441 }
5442 task = r.task;
5443
5444 int N = mPendingThumbnails.size();
5445 int i=0;
5446 while (i<N) {
5447 PendingThumbnailsRecord pr =
5448 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
5449 //System.out.println("Looking in " + pr.pendingRecords);
5450 if (pr.pendingRecords.remove(r)) {
5451 if (receivers == null) {
5452 receivers = new ArrayList();
5453 }
5454 receivers.add(pr);
5455 if (pr.pendingRecords.size() == 0) {
5456 pr.finished = true;
5457 mPendingThumbnails.remove(i);
5458 N--;
5459 continue;
5460 }
5461 }
5462 i++;
5463 }
5464 }
5465
5466 if (receivers != null) {
5467 final int N = receivers.size();
5468 for (int i=0; i<N; i++) {
5469 try {
5470 PendingThumbnailsRecord pr =
5471 (PendingThumbnailsRecord)receivers.get(i);
5472 pr.receiver.newThumbnail(
5473 task != null ? task.taskId : -1, thumbnail, description);
5474 if (pr.finished) {
5475 pr.receiver.finished();
5476 }
5477 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005478 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005479 }
5480 }
5481 }
5482 }
5483
5484 // =========================================================
5485 // CONTENT PROVIDERS
5486 // =========================================================
5487
Jeff Brown10e89712011-07-08 18:52:57 -07005488 private final List<ProviderInfo> generateApplicationProvidersLocked(ProcessRecord app) {
5489 List<ProviderInfo> providers = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005490 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005491 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005492 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005493 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005494 } catch (RemoteException ex) {
5495 }
5496 if (providers != null) {
5497 final int N = providers.size();
5498 for (int i=0; i<N; i++) {
5499 ProviderInfo cpi =
5500 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005501 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005502 if (cpr == null) {
5503 cpr = new ContentProviderRecord(cpi, app.info);
5504 mProvidersByClass.put(cpi.name, cpr);
5505 }
5506 app.pubProviders.put(cpi.name, cpr);
5507 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005508 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005509 }
5510 }
5511 return providers;
5512 }
5513
5514 private final String checkContentProviderPermissionLocked(
Dianne Hackbornb424b632010-08-18 15:59:05 -07005515 ProviderInfo cpi, ProcessRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005516 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
5517 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
5518 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005519 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005520 == PackageManager.PERMISSION_GRANTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005521 return null;
5522 }
5523 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005524 cpi.applicationInfo.uid, cpi.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005525 == PackageManager.PERMISSION_GRANTED) {
5526 return null;
5527 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005528
5529 PathPermission[] pps = cpi.pathPermissions;
5530 if (pps != null) {
5531 int i = pps.length;
5532 while (i > 0) {
5533 i--;
5534 PathPermission pp = pps[i];
5535 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005536 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005537 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005538 return null;
5539 }
5540 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005541 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005542 == PackageManager.PERMISSION_GRANTED) {
5543 return null;
5544 }
5545 }
5546 }
5547
Dianne Hackbornb424b632010-08-18 15:59:05 -07005548 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
5549 if (perms != null) {
5550 for (Map.Entry<Uri, UriPermission> uri : perms.entrySet()) {
5551 if (uri.getKey().getAuthority().equals(cpi.authority)) {
5552 return null;
5553 }
5554 }
5555 }
5556
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005557 String msg;
5558 if (!cpi.exported) {
5559 msg = "Permission Denial: opening provider " + cpi.name
5560 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5561 + ", uid=" + callingUid + ") that is not exported from uid "
5562 + cpi.applicationInfo.uid;
5563 } else {
5564 msg = "Permission Denial: opening provider " + cpi.name
5565 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5566 + ", uid=" + callingUid + ") requires "
5567 + cpi.readPermission + " or " + cpi.writePermission;
5568 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005569 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005570 return msg;
5571 }
5572
5573 private final ContentProviderHolder getContentProviderImpl(
5574 IApplicationThread caller, String name) {
5575 ContentProviderRecord cpr;
5576 ProviderInfo cpi = null;
5577
5578 synchronized(this) {
5579 ProcessRecord r = null;
5580 if (caller != null) {
5581 r = getRecordForAppLocked(caller);
5582 if (r == null) {
5583 throw new SecurityException(
5584 "Unable to find app for caller " + caller
5585 + " (pid=" + Binder.getCallingPid()
5586 + ") when getting content provider " + name);
5587 }
5588 }
5589
5590 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07005591 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005592 if (cpr != null) {
5593 cpi = cpr.info;
Dianne Hackbornb424b632010-08-18 15:59:05 -07005594 String msg;
5595 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5596 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005597 }
5598
5599 if (r != null && cpr.canRunHere(r)) {
5600 // This provider has been published or is in the process
5601 // of being published... but it is also allowed to run
5602 // in the caller's process, so don't make a connection
5603 // and just let the caller instantiate its own instance.
5604 if (cpr.provider != null) {
5605 // don't give caller the provider object, it needs
5606 // to make its own.
5607 cpr = new ContentProviderRecord(cpr);
5608 }
5609 return cpr;
5610 }
5611
5612 final long origId = Binder.clearCallingIdentity();
5613
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005614 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005615 // return it right away.
5616 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005617 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005618 "Adding provider requested by "
5619 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005620 + cpr.info.processName);
5621 Integer cnt = r.conProviders.get(cpr);
5622 if (cnt == null) {
5623 r.conProviders.put(cpr, new Integer(1));
5624 } else {
5625 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5626 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005627 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07005628 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
5629 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07005630 // make sure to count it as being accessed and thus
5631 // back up on the LRU list. This is good because
5632 // content providers are often expensive to start.
5633 updateLruProcessLocked(cpr.app, false, true);
5634 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07005635 } else {
5636 cpr.externals++;
5637 }
5638
5639 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005640 updateOomAdjLocked(cpr.app);
5641 }
5642
5643 Binder.restoreCallingIdentity(origId);
5644
5645 } else {
5646 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005647 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005648 resolveContentProvider(name,
5649 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005650 } catch (RemoteException ex) {
5651 }
5652 if (cpi == null) {
5653 return null;
5654 }
5655
Dianne Hackbornb424b632010-08-18 15:59:05 -07005656 String msg;
5657 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5658 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005659 }
5660
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07005661 if (!mProcessesReady && !mDidUpdate && !mWaitingUpdate
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005662 && !cpi.processName.equals("system")) {
5663 // If this content provider does not run in the system
5664 // process, and the system is not yet ready to run other
5665 // processes, then fail fast instead of hanging.
5666 throw new IllegalArgumentException(
5667 "Attempt to launch content provider before system ready");
5668 }
5669
Dianne Hackborn860755f2010-06-03 18:47:52 -07005670 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005671 final boolean firstClass = cpr == null;
5672 if (firstClass) {
5673 try {
5674 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005675 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005676 getApplicationInfo(
5677 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005678 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005679 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005680 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005681 + cpi.name);
5682 return null;
5683 }
5684 cpr = new ContentProviderRecord(cpi, ai);
5685 } catch (RemoteException ex) {
5686 // pm is in same process, this will never happen.
5687 }
5688 }
5689
5690 if (r != null && cpr.canRunHere(r)) {
5691 // If this is a multiprocess provider, then just return its
5692 // info and allow the caller to instantiate it. Only do
5693 // this if the provider is the same user as the caller's
5694 // process, or can run as root (so can be in any process).
5695 return cpr;
5696 }
5697
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005698 if (DEBUG_PROVIDER) {
5699 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08005700 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005701 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005702 }
5703
5704 // This is single process, and our app is now connecting to it.
5705 // See if we are already in the process of launching this
5706 // provider.
5707 final int N = mLaunchingProviders.size();
5708 int i;
5709 for (i=0; i<N; i++) {
5710 if (mLaunchingProviders.get(i) == cpr) {
5711 break;
5712 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005713 }
5714
5715 // If the provider is not already being launched, then get it
5716 // started.
5717 if (i >= N) {
5718 final long origId = Binder.clearCallingIdentity();
Dianne Hackborne7f97212011-02-24 14:40:20 -08005719
5720 try {
5721 // Content provider is now in use, its package can't be stopped.
5722 try {
5723 AppGlobals.getPackageManager().setPackageStoppedState(
5724 cpr.appInfo.packageName, false);
5725 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08005726 } catch (IllegalArgumentException e) {
5727 Slog.w(TAG, "Failed trying to unstop package "
5728 + cpr.appInfo.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08005729 }
5730
5731 ProcessRecord proc = startProcessLocked(cpi.processName,
5732 cpr.appInfo, false, 0, "content provider",
5733 new ComponentName(cpi.applicationInfo.packageName,
5734 cpi.name), false);
5735 if (proc == null) {
5736 Slog.w(TAG, "Unable to launch app "
5737 + cpi.applicationInfo.packageName + "/"
5738 + cpi.applicationInfo.uid + " for provider "
5739 + name + ": process is bad");
5740 return null;
5741 }
5742 cpr.launchingApp = proc;
5743 mLaunchingProviders.add(cpr);
5744 } finally {
5745 Binder.restoreCallingIdentity(origId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005746 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005747 }
5748
5749 // Make sure the provider is published (the same provider class
5750 // may be published under multiple names).
5751 if (firstClass) {
5752 mProvidersByClass.put(cpi.name, cpr);
5753 }
5754 mProvidersByName.put(name, cpr);
5755
5756 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005757 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005758 "Adding provider requested by "
5759 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005760 + cpr.info.processName);
5761 Integer cnt = r.conProviders.get(cpr);
5762 if (cnt == null) {
5763 r.conProviders.put(cpr, new Integer(1));
5764 } else {
5765 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5766 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005767 cpr.clients.add(r);
5768 } else {
5769 cpr.externals++;
5770 }
5771 }
5772 }
5773
5774 // Wait for the provider to be published...
5775 synchronized (cpr) {
5776 while (cpr.provider == null) {
5777 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005778 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005779 + cpi.applicationInfo.packageName + "/"
5780 + cpi.applicationInfo.uid + " for provider "
5781 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005782 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005783 cpi.applicationInfo.packageName,
5784 cpi.applicationInfo.uid, name);
5785 return null;
5786 }
5787 try {
5788 cpr.wait();
5789 } catch (InterruptedException ex) {
5790 }
5791 }
5792 }
5793 return cpr;
5794 }
5795
5796 public final ContentProviderHolder getContentProvider(
5797 IApplicationThread caller, String name) {
5798 if (caller == null) {
5799 String msg = "null IApplicationThread when getting content provider "
5800 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005801 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005802 throw new SecurityException(msg);
5803 }
5804
5805 return getContentProviderImpl(caller, name);
5806 }
5807
5808 private ContentProviderHolder getContentProviderExternal(String name) {
5809 return getContentProviderImpl(null, name);
5810 }
5811
5812 /**
5813 * Drop a content provider from a ProcessRecord's bookkeeping
5814 * @param cpr
5815 */
5816 public void removeContentProvider(IApplicationThread caller, String name) {
5817 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005818 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005819 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005820 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005821 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005822 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005823 return;
5824 }
5825 final ProcessRecord r = getRecordForAppLocked(caller);
5826 if (r == null) {
5827 throw new SecurityException(
5828 "Unable to find app for caller " + caller +
5829 " when removing content provider " + name);
5830 }
5831 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005832 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005833 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005834 + r.info.processName + " from process "
5835 + localCpr.appInfo.processName);
5836 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005837 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08005838 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005839 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005840 return;
5841 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005842 Integer cnt = r.conProviders.get(localCpr);
5843 if (cnt == null || cnt.intValue() <= 1) {
5844 localCpr.clients.remove(r);
5845 r.conProviders.remove(localCpr);
5846 } else {
5847 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
5848 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005849 }
5850 updateOomAdjLocked();
5851 }
5852 }
5853
5854 private void removeContentProviderExternal(String name) {
5855 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005856 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005857 if(cpr == null) {
5858 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005859 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005860 return;
5861 }
5862
5863 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005864 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005865 localCpr.externals--;
5866 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005867 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005868 }
5869 updateOomAdjLocked();
5870 }
5871 }
5872
5873 public final void publishContentProviders(IApplicationThread caller,
5874 List<ContentProviderHolder> providers) {
5875 if (providers == null) {
5876 return;
5877 }
5878
5879 synchronized(this) {
5880 final ProcessRecord r = getRecordForAppLocked(caller);
5881 if (r == null) {
5882 throw new SecurityException(
5883 "Unable to find app for caller " + caller
5884 + " (pid=" + Binder.getCallingPid()
5885 + ") when publishing content providers");
5886 }
5887
5888 final long origId = Binder.clearCallingIdentity();
5889
5890 final int N = providers.size();
5891 for (int i=0; i<N; i++) {
5892 ContentProviderHolder src = providers.get(i);
5893 if (src == null || src.info == null || src.provider == null) {
5894 continue;
5895 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005896 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005897 if (dst != null) {
5898 mProvidersByClass.put(dst.info.name, dst);
5899 String names[] = dst.info.authority.split(";");
5900 for (int j = 0; j < names.length; j++) {
5901 mProvidersByName.put(names[j], dst);
5902 }
5903
5904 int NL = mLaunchingProviders.size();
5905 int j;
5906 for (j=0; j<NL; j++) {
5907 if (mLaunchingProviders.get(j) == dst) {
5908 mLaunchingProviders.remove(j);
5909 j--;
5910 NL--;
5911 }
5912 }
5913 synchronized (dst) {
5914 dst.provider = src.provider;
5915 dst.app = r;
5916 dst.notifyAll();
5917 }
5918 updateOomAdjLocked(r);
5919 }
5920 }
5921
5922 Binder.restoreCallingIdentity(origId);
5923 }
5924 }
5925
5926 public static final void installSystemProviders() {
Jeff Brown10e89712011-07-08 18:52:57 -07005927 List<ProviderInfo> providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06005928 synchronized (mSelf) {
5929 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
5930 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005931 if (providers != null) {
5932 for (int i=providers.size()-1; i>=0; i--) {
5933 ProviderInfo pi = (ProviderInfo)providers.get(i);
5934 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5935 Slog.w(TAG, "Not installing system proc provider " + pi.name
5936 + ": not system .apk");
5937 providers.remove(i);
5938 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005939 }
5940 }
5941 }
Josh Bartel2ecce342010-02-25 10:55:48 -06005942 if (providers != null) {
5943 mSystemThread.installSystemProviders(providers);
5944 }
Svetoslav Ganov54d068e2011-03-02 12:58:40 -08005945
5946 mSelf.mCoreSettingsObserver = new CoreSettingsObserver(mSelf);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005947 }
5948
Dianne Hackborncca1f0e2010-09-26 18:34:53 -07005949 /**
5950 * Allows app to retrieve the MIME type of a URI without having permission
5951 * to access its content provider.
5952 *
5953 * CTS tests for this functionality can be run with "runtest cts-appsecurity".
5954 *
5955 * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
5956 * src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
5957 */
5958 public String getProviderMimeType(Uri uri) {
5959 final String name = uri.getAuthority();
5960 final long ident = Binder.clearCallingIdentity();
5961 ContentProviderHolder holder = null;
5962
5963 try {
5964 holder = getContentProviderExternal(name);
5965 if (holder != null) {
5966 return holder.provider.getType(uri);
5967 }
5968 } catch (RemoteException e) {
5969 Log.w(TAG, "Content provider dead retrieving " + uri, e);
5970 return null;
5971 } finally {
5972 if (holder != null) {
5973 removeContentProviderExternal(name);
5974 }
5975 Binder.restoreCallingIdentity(ident);
5976 }
5977
5978 return null;
5979 }
5980
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005981 // =========================================================
5982 // GLOBAL MANAGEMENT
5983 // =========================================================
5984
5985 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
5986 ApplicationInfo info, String customProcess) {
5987 String proc = customProcess != null ? customProcess : info.processName;
5988 BatteryStatsImpl.Uid.Proc ps = null;
5989 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5990 synchronized (stats) {
5991 ps = stats.getProcessStatsLocked(info.uid, proc);
5992 }
5993 return new ProcessRecord(ps, thread, info, proc);
5994 }
5995
5996 final ProcessRecord addAppLocked(ApplicationInfo info) {
5997 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
5998
5999 if (app == null) {
6000 app = newProcessRecordLocked(null, info, null);
6001 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006002 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006003 }
6004
Dianne Hackborne7f97212011-02-24 14:40:20 -08006005 // This package really, really can not be stopped.
6006 try {
6007 AppGlobals.getPackageManager().setPackageStoppedState(
6008 info.packageName, false);
6009 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08006010 } catch (IllegalArgumentException e) {
6011 Slog.w(TAG, "Failed trying to unstop package "
6012 + info.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08006013 }
6014
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006015 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
6016 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
6017 app.persistent = true;
6018 app.maxAdj = CORE_SERVER_ADJ;
6019 }
6020 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
6021 mPersistentStartingProcesses.add(app);
6022 startProcessLocked(app, "added application", app.processName);
6023 }
6024
6025 return app;
6026 }
6027
6028 public void unhandledBack() {
6029 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
6030 "unhandledBack()");
6031
6032 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006033 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08006034 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006035 TAG, "Performing unhandledBack(): stack size = " + count);
6036 if (count > 1) {
6037 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006038 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006039 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
6040 Binder.restoreCallingIdentity(origId);
6041 }
6042 }
6043 }
6044
6045 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
6046 String name = uri.getAuthority();
6047 ContentProviderHolder cph = getContentProviderExternal(name);
6048 ParcelFileDescriptor pfd = null;
6049 if (cph != null) {
6050 // We record the binder invoker's uid in thread-local storage before
6051 // going to the content provider to open the file. Later, in the code
6052 // that handles all permissions checks, we look for this uid and use
6053 // that rather than the Activity Manager's own uid. The effect is that
6054 // we do the check against the caller's permissions even though it looks
6055 // to the content provider like the Activity Manager itself is making
6056 // the request.
6057 sCallerIdentity.set(new Identity(
6058 Binder.getCallingPid(), Binder.getCallingUid()));
6059 try {
6060 pfd = cph.provider.openFile(uri, "r");
6061 } catch (FileNotFoundException e) {
6062 // do nothing; pfd will be returned null
6063 } finally {
6064 // Ensure that whatever happens, we clean up the identity state
6065 sCallerIdentity.remove();
6066 }
6067
6068 // We've got the fd now, so we're done with the provider.
6069 removeContentProviderExternal(name);
6070 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006071 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006072 }
6073 return pfd;
6074 }
6075
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006076 // Actually is sleeping or shutting down or whatever else in the future
6077 // is an inactive state.
6078 public boolean isSleeping() {
6079 return mSleeping || mShuttingDown;
6080 }
6081
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006082 public void goingToSleep() {
6083 synchronized(this) {
6084 mSleeping = true;
6085 mWindowManager.setEventDispatching(false);
6086
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006087 mMainStack.stopIfSleepingLocked();
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07006088
6089 // Initialize the wake times of all processes.
Dianne Hackborn287952c2010-09-22 22:34:31 -07006090 checkExcessivePowerUsageLocked(false);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07006091 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
6092 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07006093 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006094 }
6095 }
6096
Dianne Hackborn55280a92009-05-07 15:53:46 -07006097 public boolean shutdown(int timeout) {
6098 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
6099 != PackageManager.PERMISSION_GRANTED) {
6100 throw new SecurityException("Requires permission "
6101 + android.Manifest.permission.SHUTDOWN);
6102 }
6103
6104 boolean timedout = false;
6105
6106 synchronized(this) {
6107 mShuttingDown = true;
6108 mWindowManager.setEventDispatching(false);
6109
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006110 if (mMainStack.mResumedActivity != null) {
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006111 mMainStack.stopIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07006112 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006113 while (mMainStack.mResumedActivity != null
6114 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07006115 long delay = endTime - System.currentTimeMillis();
6116 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006117 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07006118 timedout = true;
6119 break;
6120 }
6121 try {
6122 this.wait();
6123 } catch (InterruptedException e) {
6124 }
6125 }
6126 }
6127 }
6128
6129 mUsageStatsService.shutdown();
6130 mBatteryStatsService.shutdown();
6131
6132 return timedout;
6133 }
6134
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006135 public final void activitySlept(IBinder token) {
6136 if (localLOGV) Slog.v(
6137 TAG, "Activity slept: token=" + token);
6138
6139 ActivityRecord r = null;
6140
6141 final long origId = Binder.clearCallingIdentity();
6142
6143 synchronized (this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07006144 r = mMainStack.isInStackLocked(token);
6145 if (r != null) {
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006146 mMainStack.activitySleptLocked(r);
6147 }
6148 }
6149
6150 Binder.restoreCallingIdentity(origId);
6151 }
6152
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006153 public void wakingUp() {
6154 synchronized(this) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006155 mWindowManager.setEventDispatching(true);
6156 mSleeping = false;
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006157 mMainStack.awakeFromSleepingLocked();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006158 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006159 }
6160 }
6161
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006162 public void stopAppSwitches() {
6163 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
6164 != PackageManager.PERMISSION_GRANTED) {
6165 throw new SecurityException("Requires permission "
6166 + android.Manifest.permission.STOP_APP_SWITCHES);
6167 }
6168
6169 synchronized(this) {
6170 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
6171 + APP_SWITCH_DELAY_TIME;
6172 mDidAppSwitch = false;
6173 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
6174 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
6175 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
6176 }
6177 }
6178
6179 public void resumeAppSwitches() {
6180 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
6181 != PackageManager.PERMISSION_GRANTED) {
6182 throw new SecurityException("Requires permission "
6183 + android.Manifest.permission.STOP_APP_SWITCHES);
6184 }
6185
6186 synchronized(this) {
6187 // Note that we don't execute any pending app switches... we will
6188 // let those wait until either the timeout, or the next start
6189 // activity request.
6190 mAppSwitchesAllowedTime = 0;
6191 }
6192 }
6193
6194 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
6195 String name) {
6196 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
6197 return true;
6198 }
6199
6200 final int perm = checkComponentPermission(
6201 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08006202 callingUid, -1, true);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006203 if (perm == PackageManager.PERMISSION_GRANTED) {
6204 return true;
6205 }
6206
Joe Onorato8a9b2202010-02-26 18:56:32 -08006207 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006208 return false;
6209 }
6210
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006211 public void setDebugApp(String packageName, boolean waitForDebugger,
6212 boolean persistent) {
6213 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
6214 "setDebugApp()");
6215
6216 // Note that this is not really thread safe if there are multiple
6217 // callers into it at the same time, but that's not a situation we
6218 // care about.
6219 if (persistent) {
6220 final ContentResolver resolver = mContext.getContentResolver();
6221 Settings.System.putString(
6222 resolver, Settings.System.DEBUG_APP,
6223 packageName);
6224 Settings.System.putInt(
6225 resolver, Settings.System.WAIT_FOR_DEBUGGER,
6226 waitForDebugger ? 1 : 0);
6227 }
6228
6229 synchronized (this) {
6230 if (!persistent) {
6231 mOrigDebugApp = mDebugApp;
6232 mOrigWaitForDebugger = mWaitForDebugger;
6233 }
6234 mDebugApp = packageName;
6235 mWaitForDebugger = waitForDebugger;
6236 mDebugTransient = !persistent;
6237 if (packageName != null) {
6238 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006239 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006240 Binder.restoreCallingIdentity(origId);
6241 }
6242 }
6243 }
6244
6245 public void setAlwaysFinish(boolean enabled) {
6246 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
6247 "setAlwaysFinish()");
6248
6249 Settings.System.putInt(
6250 mContext.getContentResolver(),
6251 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
6252
6253 synchronized (this) {
6254 mAlwaysFinishActivities = enabled;
6255 }
6256 }
6257
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006258 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006259 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006260 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006261 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006262 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006263 }
6264 }
6265
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08006266 public boolean isUserAMonkey() {
6267 // For now the fact that there is a controller implies
6268 // we have a monkey.
6269 synchronized (this) {
6270 return mController != null;
6271 }
6272 }
6273
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006274 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06006275 synchronized (this) {
6276 mWatchers.register(watcher);
6277 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006278 }
6279
6280 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06006281 synchronized (this) {
6282 mWatchers.unregister(watcher);
6283 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006284 }
6285
Jeff Sharkeya4620792011-05-20 15:29:23 -07006286 public void registerProcessObserver(IProcessObserver observer) {
6287 mProcessObservers.register(observer);
6288 }
6289
6290 public void unregisterProcessObserver(IProcessObserver observer) {
6291 mProcessObservers.unregister(observer);
6292 }
6293
Daniel Sandler69a48172010-06-23 16:29:36 -04006294 public void setImmersive(IBinder token, boolean immersive) {
6295 synchronized(this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07006296 ActivityRecord r = mMainStack.isInStackLocked(token);
6297 if (r == null) {
Daniel Sandler69a48172010-06-23 16:29:36 -04006298 throw new IllegalArgumentException();
6299 }
Daniel Sandler69a48172010-06-23 16:29:36 -04006300 r.immersive = immersive;
6301 }
6302 }
6303
6304 public boolean isImmersive(IBinder token) {
6305 synchronized (this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07006306 ActivityRecord r = mMainStack.isInStackLocked(token);
6307 if (r == null) {
Daniel Sandler69a48172010-06-23 16:29:36 -04006308 throw new IllegalArgumentException();
6309 }
Daniel Sandler69a48172010-06-23 16:29:36 -04006310 return r.immersive;
6311 }
6312 }
6313
6314 public boolean isTopActivityImmersive() {
6315 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006316 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Daniel Sandler69a48172010-06-23 16:29:36 -04006317 return (r != null) ? r.immersive : false;
6318 }
6319 }
6320
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006321 public final void enterSafeMode() {
6322 synchronized(this) {
6323 // It only makes sense to do this before the system is ready
6324 // and started launching other packages.
6325 if (!mSystemReady) {
6326 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006327 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006328 } catch (RemoteException e) {
6329 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006330 }
6331 }
6332 }
6333
Jeff Brownb09abc12011-01-13 21:08:27 -08006334 public final void showSafeModeOverlay() {
6335 View v = LayoutInflater.from(mContext).inflate(
6336 com.android.internal.R.layout.safe_mode, null);
6337 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
6338 lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
6339 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
6340 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
6341 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
6342 lp.format = v.getBackground().getOpacity();
6343 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
6344 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
6345 ((WindowManager)mContext.getSystemService(
6346 Context.WINDOW_SERVICE)).addView(v, lp);
6347 }
6348
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006349 public void noteWakeupAlarm(IIntentSender sender) {
6350 if (!(sender instanceof PendingIntentRecord)) {
6351 return;
6352 }
6353 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
6354 synchronized (stats) {
6355 if (mBatteryStatsService.isOnBattery()) {
6356 mBatteryStatsService.enforceCallingPermission();
6357 PendingIntentRecord rec = (PendingIntentRecord)sender;
6358 int MY_UID = Binder.getCallingUid();
6359 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
6360 BatteryStatsImpl.Uid.Pkg pkg =
6361 stats.getPackageStatsLocked(uid, rec.key.packageName);
6362 pkg.incWakeupsLocked();
6363 }
6364 }
6365 }
6366
Dianne Hackborn64825172011-03-02 21:32:58 -08006367 public boolean killPids(int[] pids, String pReason, boolean secure) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006368 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006369 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006370 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006371 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006372 // XXX Note: don't acquire main activity lock here, because the window
6373 // manager calls in with its locks held.
6374
6375 boolean killed = false;
6376 synchronized (mPidsSelfLocked) {
6377 int[] types = new int[pids.length];
6378 int worstType = 0;
6379 for (int i=0; i<pids.length; i++) {
6380 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6381 if (proc != null) {
6382 int type = proc.setAdj;
6383 types[i] = type;
6384 if (type > worstType) {
6385 worstType = type;
6386 }
6387 }
6388 }
6389
Dianne Hackborn64825172011-03-02 21:32:58 -08006390 // If the worst oom_adj is somewhere in the hidden proc LRU range,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006391 // then constrain it so we will kill all hidden procs.
6392 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
6393 worstType = HIDDEN_APP_MIN_ADJ;
6394 }
Dianne Hackborn64825172011-03-02 21:32:58 -08006395
6396 // If this is not a secure call, don't let it kill processes that
6397 // are important.
6398 if (!secure && worstType < SECONDARY_SERVER_ADJ) {
6399 worstType = SECONDARY_SERVER_ADJ;
6400 }
6401
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006402 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006403 for (int i=0; i<pids.length; i++) {
6404 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6405 if (proc == null) {
6406 continue;
6407 }
6408 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006409 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07006410 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006411 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
6412 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006413 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006414 proc.killedBackground = true;
6415 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006416 }
6417 }
6418 }
6419 return killed;
6420 }
6421
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006422 public final void startRunning(String pkg, String cls, String action,
6423 String data) {
6424 synchronized(this) {
6425 if (mStartRunning) {
6426 return;
6427 }
6428 mStartRunning = true;
6429 mTopComponent = pkg != null && cls != null
6430 ? new ComponentName(pkg, cls) : null;
6431 mTopAction = action != null ? action : Intent.ACTION_MAIN;
6432 mTopData = data;
6433 if (!mSystemReady) {
6434 return;
6435 }
6436 }
6437
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006438 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006439 }
6440
6441 private void retrieveSettings() {
6442 final ContentResolver resolver = mContext.getContentResolver();
6443 String debugApp = Settings.System.getString(
6444 resolver, Settings.System.DEBUG_APP);
6445 boolean waitForDebugger = Settings.System.getInt(
6446 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
6447 boolean alwaysFinishActivities = Settings.System.getInt(
6448 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
6449
6450 Configuration configuration = new Configuration();
6451 Settings.System.getConfiguration(resolver, configuration);
6452
6453 synchronized (this) {
6454 mDebugApp = mOrigDebugApp = debugApp;
6455 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
6456 mAlwaysFinishActivities = alwaysFinishActivities;
6457 // This happens before any activities are started, so we can
6458 // change mConfiguration in-place.
6459 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08006460 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006461 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006462 }
6463 }
6464
6465 public boolean testIsSystemReady() {
6466 // no need to synchronize(this) just to read & return the value
6467 return mSystemReady;
6468 }
6469
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006470 private static File getCalledPreBootReceiversFile() {
6471 File dataDir = Environment.getDataDirectory();
6472 File systemDir = new File(dataDir, "system");
6473 File fname = new File(systemDir, "called_pre_boots.dat");
6474 return fname;
6475 }
6476
6477 private static ArrayList<ComponentName> readLastDonePreBootReceivers() {
6478 ArrayList<ComponentName> lastDoneReceivers = new ArrayList<ComponentName>();
6479 File file = getCalledPreBootReceiversFile();
6480 FileInputStream fis = null;
6481 try {
6482 fis = new FileInputStream(file);
6483 DataInputStream dis = new DataInputStream(new BufferedInputStream(fis, 2048));
6484 int vers = dis.readInt();
6485 String codename = dis.readUTF();
6486 if (vers == android.os.Build.VERSION.SDK_INT
6487 && codename.equals(android.os.Build.VERSION.CODENAME)) {
6488 int num = dis.readInt();
6489 while (num > 0) {
6490 num--;
6491 String pkg = dis.readUTF();
6492 String cls = dis.readUTF();
6493 lastDoneReceivers.add(new ComponentName(pkg, cls));
6494 }
6495 }
6496 } catch (FileNotFoundException e) {
6497 } catch (IOException e) {
6498 Slog.w(TAG, "Failure reading last done pre-boot receivers", e);
6499 } finally {
6500 if (fis != null) {
6501 try {
6502 fis.close();
6503 } catch (IOException e) {
6504 }
6505 }
6506 }
6507 return lastDoneReceivers;
6508 }
6509
6510 private static void writeLastDonePreBootReceivers(ArrayList<ComponentName> list) {
6511 File file = getCalledPreBootReceiversFile();
6512 FileOutputStream fos = null;
6513 DataOutputStream dos = null;
6514 try {
6515 Slog.i(TAG, "Writing new set of last done pre-boot receivers...");
6516 fos = new FileOutputStream(file);
6517 dos = new DataOutputStream(new BufferedOutputStream(fos, 2048));
6518 dos.writeInt(android.os.Build.VERSION.SDK_INT);
6519 dos.writeUTF(android.os.Build.VERSION.CODENAME);
6520 dos.writeInt(list.size());
6521 for (int i=0; i<list.size(); i++) {
6522 dos.writeUTF(list.get(i).getPackageName());
6523 dos.writeUTF(list.get(i).getClassName());
6524 }
6525 } catch (IOException e) {
6526 Slog.w(TAG, "Failure writing last done pre-boot receivers", e);
6527 file.delete();
6528 } finally {
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07006529 FileUtils.sync(fos);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006530 if (dos != null) {
6531 try {
6532 dos.close();
6533 } catch (IOException e) {
6534 // TODO Auto-generated catch block
6535 e.printStackTrace();
6536 }
6537 }
6538 }
6539 }
6540
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006541 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006542 synchronized(this) {
6543 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006544 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006545 return;
6546 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006547
6548 // Check to see if there are any update receivers to run.
6549 if (!mDidUpdate) {
6550 if (mWaitingUpdate) {
6551 return;
6552 }
6553 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
6554 List<ResolveInfo> ris = null;
6555 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006556 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006557 intent, null, 0);
6558 } catch (RemoteException e) {
6559 }
6560 if (ris != null) {
6561 for (int i=ris.size()-1; i>=0; i--) {
6562 if ((ris.get(i).activityInfo.applicationInfo.flags
6563 &ApplicationInfo.FLAG_SYSTEM) == 0) {
6564 ris.remove(i);
6565 }
6566 }
6567 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006568
6569 ArrayList<ComponentName> lastDoneReceivers = readLastDonePreBootReceivers();
6570
6571 final ArrayList<ComponentName> doneReceivers = new ArrayList<ComponentName>();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006572 for (int i=0; i<ris.size(); i++) {
6573 ActivityInfo ai = ris.get(i).activityInfo;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006574 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6575 if (lastDoneReceivers.contains(comp)) {
6576 ris.remove(i);
6577 i--;
6578 }
6579 }
6580
6581 for (int i=0; i<ris.size(); i++) {
6582 ActivityInfo ai = ris.get(i).activityInfo;
6583 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6584 doneReceivers.add(comp);
6585 intent.setComponent(comp);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006586 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08006587 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006588 finisher = new IIntentReceiver.Stub() {
6589 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07006590 String data, Bundle extras, boolean ordered,
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006591 boolean sticky) {
6592 // The raw IIntentReceiver interface is called
6593 // with the AM lock held, so redispatch to
6594 // execute our code without the lock.
6595 mHandler.post(new Runnable() {
6596 public void run() {
6597 synchronized (ActivityManagerService.this) {
6598 mDidUpdate = true;
6599 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006600 writeLastDonePreBootReceivers(doneReceivers);
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006601 systemReady(goingCallback);
6602 }
6603 });
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006604 }
6605 };
6606 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006607 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006608 broadcastIntentLocked(null, null, intent, null, finisher,
6609 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08006610 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006611 mWaitingUpdate = true;
6612 }
6613 }
6614 }
6615 if (mWaitingUpdate) {
6616 return;
6617 }
6618 mDidUpdate = true;
6619 }
6620
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006621 mSystemReady = true;
6622 if (!mStartRunning) {
6623 return;
6624 }
6625 }
6626
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006627 ArrayList<ProcessRecord> procsToKill = null;
6628 synchronized(mPidsSelfLocked) {
6629 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
6630 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
6631 if (!isAllowedWhileBooting(proc.info)){
6632 if (procsToKill == null) {
6633 procsToKill = new ArrayList<ProcessRecord>();
6634 }
6635 procsToKill.add(proc);
6636 }
6637 }
6638 }
6639
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006640 synchronized(this) {
6641 if (procsToKill != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006642 for (int i=procsToKill.size()-1; i>=0; i--) {
6643 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08006644 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006645 removeProcessLocked(proc, true);
6646 }
6647 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006648
6649 // Now that we have cleaned up any update processes, we
6650 // are ready to start launching real processes and know that
6651 // we won't trample on them any more.
6652 mProcessesReady = true;
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006653 }
6654
Joe Onorato8a9b2202010-02-26 18:56:32 -08006655 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006656 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006657 SystemClock.uptimeMillis());
6658
6659 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006660 // Make sure we have no pre-ready processes sitting around.
6661
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006662 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
6663 ResolveInfo ri = mContext.getPackageManager()
6664 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07006665 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006666 CharSequence errorMsg = null;
6667 if (ri != null) {
6668 ActivityInfo ai = ri.activityInfo;
6669 ApplicationInfo app = ai.applicationInfo;
6670 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
6671 mTopAction = Intent.ACTION_FACTORY_TEST;
6672 mTopData = null;
6673 mTopComponent = new ComponentName(app.packageName,
6674 ai.name);
6675 } else {
6676 errorMsg = mContext.getResources().getText(
6677 com.android.internal.R.string.factorytest_not_system);
6678 }
6679 } else {
6680 errorMsg = mContext.getResources().getText(
6681 com.android.internal.R.string.factorytest_no_action);
6682 }
6683 if (errorMsg != null) {
6684 mTopAction = null;
6685 mTopData = null;
6686 mTopComponent = null;
6687 Message msg = Message.obtain();
6688 msg.what = SHOW_FACTORY_ERROR_MSG;
6689 msg.getData().putCharSequence("msg", errorMsg);
6690 mHandler.sendMessage(msg);
6691 }
6692 }
6693 }
6694
6695 retrieveSettings();
6696
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006697 if (goingCallback != null) goingCallback.run();
6698
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006699 synchronized (this) {
6700 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
6701 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006702 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07006703 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006704 if (apps != null) {
6705 int N = apps.size();
6706 int i;
6707 for (i=0; i<N; i++) {
6708 ApplicationInfo info
6709 = (ApplicationInfo)apps.get(i);
6710 if (info != null &&
6711 !info.packageName.equals("android")) {
6712 addAppLocked(info);
6713 }
6714 }
6715 }
6716 } catch (RemoteException ex) {
6717 // pm is in same process, this will never happen.
6718 }
6719 }
6720
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006721 // Start up initial activity.
6722 mBooting = true;
6723
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006724 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006725 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006726 Message msg = Message.obtain();
6727 msg.what = SHOW_UID_ERROR_MSG;
6728 mHandler.sendMessage(msg);
6729 }
6730 } catch (RemoteException e) {
6731 }
6732
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006733 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006734 }
6735 }
6736
Dan Egnorb7f03672009-12-09 16:22:32 -08006737 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006738 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006739 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006740 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006741 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006742 startAppProblemLocked(app);
6743 app.stopFreezingAllLocked();
6744 return handleAppCrashLocked(app);
6745 }
6746
Dan Egnorb7f03672009-12-09 16:22:32 -08006747 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006748 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006749 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006750 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006751 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
6752 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006753 startAppProblemLocked(app);
6754 app.stopFreezingAllLocked();
6755 }
6756
6757 /**
6758 * Generate a process error record, suitable for attachment to a ProcessRecord.
6759 *
6760 * @param app The ProcessRecord in which the error occurred.
6761 * @param condition Crashing, Application Not Responding, etc. Values are defined in
6762 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08006763 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006764 * @param shortMsg Short message describing the crash.
6765 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08006766 * @param stackTrace Full crash stack trace, may be null.
6767 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006768 * @return Returns a fully-formed AppErrorStateInfo record.
6769 */
6770 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006771 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006772 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08006773
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006774 report.condition = condition;
6775 report.processName = app.processName;
6776 report.pid = app.pid;
6777 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08006778 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006779 report.shortMsg = shortMsg;
6780 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08006781 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006782
6783 return report;
6784 }
6785
Dan Egnor42471dd2010-01-07 17:25:22 -08006786 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006787 synchronized (this) {
6788 app.crashing = false;
6789 app.crashingReport = null;
6790 app.notResponding = false;
6791 app.notRespondingReport = null;
6792 if (app.anrDialog == fromDialog) {
6793 app.anrDialog = null;
6794 }
6795 if (app.waitDialog == fromDialog) {
6796 app.waitDialog = null;
6797 }
6798 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08006799 handleAppCrashLocked(app);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07006800 Slog.i(ActivityManagerService.TAG, "Killing " + app + ": user's request");
Dianne Hackborn8633e682010-04-22 16:03:41 -07006801 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
6802 app.processName, app.setAdj, "user's request after error");
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07006803 Process.killProcessQuiet(app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006804 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006805 }
6806 }
Dan Egnor42471dd2010-01-07 17:25:22 -08006807
Dan Egnorb7f03672009-12-09 16:22:32 -08006808 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006809 long now = SystemClock.uptimeMillis();
6810
6811 Long crashTime = mProcessCrashTimes.get(app.info.processName,
6812 app.info.uid);
6813 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
6814 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006815 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006816 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006817 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006818 app.info.processName, app.info.uid);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006819 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
6820 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006821 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006822 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006823 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006824 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006825 }
6826 }
6827 if (!app.persistent) {
Dianne Hackborn070783f2010-12-29 16:46:28 -08006828 // Don't let services in this process be restarted and potentially
6829 // annoy the user repeatedly. Unless it is persistent, since those
6830 // processes run critical code.
6831 killServicesLocked(app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006832 // We don't want to start this process again until the user
6833 // explicitly does so... but for persistent process, we really
6834 // need to keep it running. If a persistent process is actually
6835 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08006836 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006837 app.info.processName);
6838 mBadProcesses.put(app.info.processName, app.info.uid, now);
6839 app.bad = true;
6840 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
6841 app.removed = true;
6842 removeProcessLocked(app, false);
Dianne Hackborncb44d962011-03-10 17:02:27 -08006843 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006844 return false;
6845 }
Dianne Hackborncb44d962011-03-10 17:02:27 -08006846 mMainStack.resumeTopActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006847 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006848 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006849 if (r.app == app) {
6850 // If the top running activity is from this crashing
6851 // process, then terminate it to avoid getting in a loop.
6852 Slog.w(TAG, " Force finishing activity "
6853 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006854 int index = mMainStack.indexOfTokenLocked(r);
6855 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006856 Activity.RESULT_CANCELED, null, "crashed");
Dianne Hackborn070783f2010-12-29 16:46:28 -08006857 // Also terminate any activities below it that aren't yet
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006858 // stopped, to avoid a situation where one will get
6859 // re-start our crashing activity once it gets resumed again.
6860 index--;
6861 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006862 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006863 if (r.state == ActivityState.RESUMED
6864 || r.state == ActivityState.PAUSING
6865 || r.state == ActivityState.PAUSED) {
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -08006866 if (!r.isHomeActivity || mHomeProcess != r.app) {
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006867 Slog.w(TAG, " Force finishing activity "
6868 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006869 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006870 Activity.RESULT_CANCELED, null, "crashed");
6871 }
6872 }
6873 }
6874 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006875 }
6876
6877 // Bump up the crash count of any services currently running in the proc.
6878 if (app.services.size() != 0) {
6879 // Any services running in the application need to be placed
6880 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07006881 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006882 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006883 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006884 sr.crashCount++;
6885 }
6886 }
Mattias Larssona4fd0072010-06-22 22:37:03 +02006887
6888 // If the crashing process is what we consider to be the "home process" and it has been
6889 // replaced by a third-party app, clear the package preferred activities from packages
6890 // with a home activity running in the process to prevent a repeatedly crashing app
6891 // from blocking the user to manually clear the list.
6892 if (app == mHomeProcess && mHomeProcess.activities.size() > 0
6893 && (mHomeProcess.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
6894 Iterator it = mHomeProcess.activities.iterator();
6895 while (it.hasNext()) {
Jean-Baptiste Queru5ea89f72010-07-30 09:30:31 -07006896 ActivityRecord r = (ActivityRecord)it.next();
Mattias Larssona4fd0072010-06-22 22:37:03 +02006897 if (r.isHomeActivity) {
6898 Log.i(TAG, "Clearing package preferred activities from " + r.packageName);
6899 try {
6900 ActivityThread.getPackageManager()
6901 .clearPackagePreferredActivities(r.packageName);
6902 } catch (RemoteException c) {
6903 // pm is in same process, this will never happen.
6904 }
6905 }
6906 }
6907 }
6908
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006909 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
6910 return true;
6911 }
6912
6913 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006914 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
6915 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006916 skipCurrentReceiverLocked(app);
6917 }
6918
6919 void skipCurrentReceiverLocked(ProcessRecord app) {
6920 boolean reschedule = false;
6921 BroadcastRecord r = app.curReceiver;
6922 if (r != null) {
6923 // The current broadcast is waiting for this app's receiver
6924 // to be finished. Looks like that's not going to happen, so
6925 // let the broadcast continue.
Jeff Brown4d94a762010-09-23 11:33:28 -07006926 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006927 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6928 r.resultExtras, r.resultAbort, true);
6929 reschedule = true;
6930 }
6931 r = mPendingBroadcast;
6932 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006933 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006934 "skip & discard pending app " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -07006935 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006936 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6937 r.resultExtras, r.resultAbort, true);
6938 reschedule = true;
6939 }
6940 if (reschedule) {
6941 scheduleBroadcastsLocked();
6942 }
6943 }
6944
Dan Egnor60d87622009-12-16 16:32:58 -08006945 /**
6946 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
6947 * The application process will exit immediately after this call returns.
6948 * @param app object of the crashing app, null for the system server
6949 * @param crashInfo describing the exception
6950 */
6951 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
Dianne Hackborncb44d962011-03-10 17:02:27 -08006952 ProcessRecord r = findAppProcess(app, "Crash");
Dan Egnor60d87622009-12-16 16:32:58 -08006953
6954 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
6955 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006956 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006957 crashInfo.exceptionClassName,
6958 crashInfo.exceptionMessage,
6959 crashInfo.throwFileName,
6960 crashInfo.throwLineNumber);
6961
Dan Egnor42471dd2010-01-07 17:25:22 -08006962 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006963
6964 crashApplication(r, crashInfo);
6965 }
6966
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006967 public void handleApplicationStrictModeViolation(
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006968 IBinder app,
6969 int violationMask,
6970 StrictMode.ViolationInfo info) {
Dianne Hackborncb44d962011-03-10 17:02:27 -08006971 ProcessRecord r = findAppProcess(app, "StrictMode");
6972 if (r == null) {
6973 return;
6974 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006975
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006976 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -08006977 Integer stackFingerprint = info.hashCode();
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006978 boolean logIt = true;
6979 synchronized (mAlreadyLoggedViolatedStacks) {
6980 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
6981 logIt = false;
6982 // TODO: sub-sample into EventLog for these, with
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006983 // the info.durationMillis? Then we'd get
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006984 // the relative pain numbers, without logging all
6985 // the stack traces repeatedly. We'd want to do
6986 // likewise in the client code, which also does
6987 // dup suppression, before the Binder call.
6988 } else {
6989 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
6990 mAlreadyLoggedViolatedStacks.clear();
6991 }
6992 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
6993 }
6994 }
6995 if (logIt) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006996 logStrictModeViolationToDropBox(r, info);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006997 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006998 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006999
7000 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
7001 AppErrorResult result = new AppErrorResult();
7002 synchronized (this) {
7003 final long origId = Binder.clearCallingIdentity();
7004
7005 Message msg = Message.obtain();
7006 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
7007 HashMap<String, Object> data = new HashMap<String, Object>();
7008 data.put("result", result);
7009 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07007010 data.put("violationMask", violationMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007011 data.put("info", info);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07007012 msg.obj = data;
7013 mHandler.sendMessage(msg);
7014
7015 Binder.restoreCallingIdentity(origId);
7016 }
7017 int res = result.get();
Dianne Hackbornb424b632010-08-18 15:59:05 -07007018 Slog.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07007019 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07007020 }
7021
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007022 // Depending on the policy in effect, there could be a bunch of
7023 // these in quick succession so we try to batch these together to
7024 // minimize disk writes, number of dropbox entries, and maximize
7025 // compression, by having more fewer, larger records.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007026 private void logStrictModeViolationToDropBox(
7027 ProcessRecord process,
7028 StrictMode.ViolationInfo info) {
7029 if (info == null) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007030 return;
7031 }
7032 final boolean isSystemApp = process == null ||
7033 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
7034 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
7035 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
7036 final DropBoxManager dbox = (DropBoxManager)
7037 mContext.getSystemService(Context.DROPBOX_SERVICE);
7038
7039 // Exit early if the dropbox isn't configured to accept this report type.
7040 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
7041
7042 boolean bufferWasEmpty;
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007043 boolean needsFlush;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007044 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
7045 synchronized (sb) {
7046 bufferWasEmpty = sb.length() == 0;
7047 appendDropBoxProcessHeaders(process, sb);
7048 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
7049 sb.append("System-App: ").append(isSystemApp).append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007050 sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
7051 if (info.violationNumThisLoop != 0) {
7052 sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
7053 }
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07007054 if (info.numAnimationsRunning != 0) {
7055 sb.append("Animations-Running: ").append(info.numAnimationsRunning).append("\n");
7056 }
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07007057 if (info.broadcastIntentAction != null) {
7058 sb.append("Broadcast-Intent-Action: ").append(info.broadcastIntentAction).append("\n");
7059 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08007060 if (info.durationMillis != -1) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007061 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007062 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08007063 if (info.numInstances != -1) {
7064 sb.append("Instance-Count: ").append(info.numInstances).append("\n");
7065 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08007066 if (info.tags != null) {
7067 for (String tag : info.tags) {
7068 sb.append("Span-Tag: ").append(tag).append("\n");
7069 }
7070 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007071 sb.append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007072 if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
7073 sb.append(info.crashInfo.stackTrace);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007074 }
7075 sb.append("\n");
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007076
7077 // Only buffer up to ~64k. Various logging bits truncate
7078 // things at 128k.
7079 needsFlush = (sb.length() > 64 * 1024);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007080 }
7081
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007082 // Flush immediately if the buffer's grown too large, or this
7083 // is a non-system app. Non-system apps are isolated with a
7084 // different tag & policy and not batched.
7085 //
7086 // Batching is useful during internal testing with
7087 // StrictMode settings turned up high. Without batching,
7088 // thousands of separate files could be created on boot.
7089 if (!isSystemApp || needsFlush) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007090 new Thread("Error dump: " + dropboxTag) {
7091 @Override
7092 public void run() {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007093 String report;
7094 synchronized (sb) {
7095 report = sb.toString();
7096 sb.delete(0, sb.length());
7097 sb.trimToSize();
7098 }
7099 if (report.length() != 0) {
7100 dbox.addText(dropboxTag, report);
7101 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007102 }
7103 }.start();
7104 return;
7105 }
7106
7107 // System app batching:
7108 if (!bufferWasEmpty) {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007109 // An existing dropbox-writing thread is outstanding, so
7110 // we don't need to start it up. The existing thread will
7111 // catch the buffer appends we just did.
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007112 return;
7113 }
7114
7115 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
7116 // (After this point, we shouldn't access AMS internal data structures.)
7117 new Thread("Error dump: " + dropboxTag) {
7118 @Override
7119 public void run() {
7120 // 5 second sleep to let stacks arrive and be batched together
7121 try {
7122 Thread.sleep(5000); // 5 seconds
7123 } catch (InterruptedException e) {}
7124
7125 String errorReport;
7126 synchronized (mStrictModeBuffer) {
7127 errorReport = mStrictModeBuffer.toString();
7128 if (errorReport.length() == 0) {
7129 return;
7130 }
7131 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
7132 mStrictModeBuffer.trimToSize();
7133 }
7134 dbox.addText(dropboxTag, errorReport);
7135 }
7136 }.start();
7137 }
7138
Dan Egnor60d87622009-12-16 16:32:58 -08007139 /**
7140 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
7141 * @param app object of the crashing app, null for the system server
7142 * @param tag reported by the caller
7143 * @param crashInfo describing the context of the error
7144 * @return true if the process should exit immediately (WTF is fatal)
7145 */
7146 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08007147 ApplicationErrorReport.CrashInfo crashInfo) {
Dianne Hackborncb44d962011-03-10 17:02:27 -08007148 ProcessRecord r = findAppProcess(app, "WTF");
Dan Egnor60d87622009-12-16 16:32:58 -08007149
7150 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
7151 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08007152 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08007153 tag, crashInfo.exceptionMessage);
7154
Dan Egnor42471dd2010-01-07 17:25:22 -08007155 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08007156
Dianne Hackborn1ab43772011-03-15 14:38:02 -07007157 if (r != null && r.pid != Process.myPid() &&
7158 Settings.Secure.getInt(mContext.getContentResolver(),
7159 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08007160 crashApplication(r, crashInfo);
7161 return true;
7162 } else {
7163 return false;
7164 }
7165 }
7166
7167 /**
7168 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
7169 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
7170 */
Dianne Hackborncb44d962011-03-10 17:02:27 -08007171 private ProcessRecord findAppProcess(IBinder app, String reason) {
Dan Egnor60d87622009-12-16 16:32:58 -08007172 if (app == null) {
7173 return null;
7174 }
7175
7176 synchronized (this) {
7177 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
7178 final int NA = apps.size();
7179 for (int ia=0; ia<NA; ia++) {
7180 ProcessRecord p = apps.valueAt(ia);
7181 if (p.thread != null && p.thread.asBinder() == app) {
7182 return p;
7183 }
7184 }
7185 }
7186
Dianne Hackborncb44d962011-03-10 17:02:27 -08007187 Slog.w(TAG, "Can't find mystery application for " + reason
7188 + " from pid=" + Binder.getCallingPid()
7189 + " uid=" + Binder.getCallingUid() + ": " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08007190 return null;
7191 }
7192 }
7193
7194 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007195 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
7196 * to append various headers to the dropbox log text.
Dan Egnor60d87622009-12-16 16:32:58 -08007197 */
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07007198 private void appendDropBoxProcessHeaders(ProcessRecord process, StringBuilder sb) {
Vairavan Srinivasan68a4e0a2011-02-14 20:45:59 -08007199 // Watchdog thread ends up invoking this function (with
7200 // a null ProcessRecord) to add the stack file to dropbox.
7201 // Do not acquire a lock on this (am) in such cases, as it
7202 // could cause a potential deadlock, if and when watchdog
7203 // is invoked due to unavailability of lock on am and it
7204 // would prevent watchdog from killing system_server.
7205 if (process == null) {
7206 sb.append("Process: system_server\n");
7207 return;
7208 }
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07007209 // Note: ProcessRecord 'process' is guarded by the service
7210 // instance. (notably process.pkgList, which could otherwise change
7211 // concurrently during execution of this method)
7212 synchronized (this) {
Vairavan Srinivasan68a4e0a2011-02-14 20:45:59 -08007213 if (process.pid == MY_PID) {
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07007214 sb.append("Process: system_server\n");
7215 } else {
7216 sb.append("Process: ").append(process.processName).append("\n");
7217 }
Dan Egnora455d192010-03-12 08:52:28 -08007218 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007219 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08007220 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
7221 for (String pkg : process.pkgList) {
7222 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08007223 try {
Dan Egnora455d192010-03-12 08:52:28 -08007224 PackageInfo pi = pm.getPackageInfo(pkg, 0);
7225 if (pi != null) {
7226 sb.append(" v").append(pi.versionCode);
7227 if (pi.versionName != null) {
7228 sb.append(" (").append(pi.versionName).append(")");
7229 }
7230 }
7231 } catch (RemoteException e) {
7232 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08007233 }
Dan Egnora455d192010-03-12 08:52:28 -08007234 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08007235 }
Dan Egnora455d192010-03-12 08:52:28 -08007236 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007237 }
7238
7239 private static String processClass(ProcessRecord process) {
7240 if (process == null || process.pid == MY_PID) {
7241 return "system_server";
7242 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
7243 return "system_app";
7244 } else {
7245 return "data_app";
7246 }
7247 }
7248
7249 /**
7250 * Write a description of an error (crash, WTF, ANR) to the drop box.
7251 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
7252 * @param process which caused the error, null means the system server
7253 * @param activity which triggered the error, null if unknown
7254 * @param parent activity related to the error, null if unknown
7255 * @param subject line related to the error, null if absent
7256 * @param report in long form describing the error, null if absent
7257 * @param logFile to include in the report, null if none
7258 * @param crashInfo giving an application stack trace, null if absent
7259 */
7260 public void addErrorToDropBox(String eventType,
7261 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
7262 final String report, final File logFile,
7263 final ApplicationErrorReport.CrashInfo crashInfo) {
7264 // NOTE -- this must never acquire the ActivityManagerService lock,
7265 // otherwise the watchdog may be prevented from resetting the system.
7266
7267 final String dropboxTag = processClass(process) + "_" + eventType;
7268 final DropBoxManager dbox = (DropBoxManager)
7269 mContext.getSystemService(Context.DROPBOX_SERVICE);
7270
7271 // Exit early if the dropbox isn't configured to accept this report type.
7272 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
7273
7274 final StringBuilder sb = new StringBuilder(1024);
7275 appendDropBoxProcessHeaders(process, sb);
Dan Egnora455d192010-03-12 08:52:28 -08007276 if (activity != null) {
7277 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
7278 }
7279 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
7280 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
7281 }
7282 if (parent != null && parent != activity) {
7283 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
7284 }
7285 if (subject != null) {
7286 sb.append("Subject: ").append(subject).append("\n");
7287 }
7288 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
Christian Lindeberg03d2ca62010-09-28 14:52:20 +02007289 if (Debug.isDebuggerConnected()) {
7290 sb.append("Debugger: Connected\n");
7291 }
Dan Egnora455d192010-03-12 08:52:28 -08007292 sb.append("\n");
7293
7294 // Do the rest in a worker thread to avoid blocking the caller on I/O
7295 // (After this point, we shouldn't access AMS internal data structures.)
7296 Thread worker = new Thread("Error dump: " + dropboxTag) {
7297 @Override
7298 public void run() {
7299 if (report != null) {
7300 sb.append(report);
7301 }
7302 if (logFile != null) {
7303 try {
7304 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
7305 } catch (IOException e) {
7306 Slog.e(TAG, "Error reading " + logFile, e);
7307 }
7308 }
7309 if (crashInfo != null && crashInfo.stackTrace != null) {
7310 sb.append(crashInfo.stackTrace);
7311 }
7312
7313 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
7314 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
7315 if (lines > 0) {
7316 sb.append("\n");
7317
7318 // Merge several logcat streams, and take the last N lines
7319 InputStreamReader input = null;
7320 try {
7321 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
7322 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
7323 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
7324
7325 try { logcat.getOutputStream().close(); } catch (IOException e) {}
7326 try { logcat.getErrorStream().close(); } catch (IOException e) {}
7327 input = new InputStreamReader(logcat.getInputStream());
7328
7329 int num;
7330 char[] buf = new char[8192];
7331 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
7332 } catch (IOException e) {
7333 Slog.e(TAG, "Error running logcat", e);
7334 } finally {
7335 if (input != null) try { input.close(); } catch (IOException e) {}
7336 }
7337 }
7338
7339 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08007340 }
Dan Egnora455d192010-03-12 08:52:28 -08007341 };
7342
7343 if (process == null || process.pid == MY_PID) {
7344 worker.run(); // We may be about to die -- need to run this synchronously
7345 } else {
7346 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08007347 }
7348 }
7349
7350 /**
7351 * Bring up the "unexpected error" dialog box for a crashing app.
7352 * Deal with edge cases (intercepts from instrumented applications,
7353 * ActivityController, error intent receivers, that sort of thing).
7354 * @param r the application crashing
7355 * @param crashInfo describing the failure
7356 */
7357 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007358 long timeMillis = System.currentTimeMillis();
7359 String shortMsg = crashInfo.exceptionClassName;
7360 String longMsg = crashInfo.exceptionMessage;
7361 String stackTrace = crashInfo.stackTrace;
7362 if (shortMsg != null && longMsg != null) {
7363 longMsg = shortMsg + ": " + longMsg;
7364 } else if (shortMsg != null) {
7365 longMsg = shortMsg;
7366 }
7367
Dan Egnor60d87622009-12-16 16:32:58 -08007368 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007369 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007370 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007371 try {
7372 String name = r != null ? r.processName : null;
7373 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08007374 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08007375 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007376 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007377 + " at watcher's request");
7378 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08007379 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007380 }
7381 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007382 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007383 }
7384 }
7385
7386 final long origId = Binder.clearCallingIdentity();
7387
7388 // If this process is running instrumentation, finish it.
7389 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007390 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007391 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08007392 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
7393 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007394 Bundle info = new Bundle();
7395 info.putString("shortMsg", shortMsg);
7396 info.putString("longMsg", longMsg);
7397 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
7398 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007399 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007400 }
7401
Dan Egnor60d87622009-12-16 16:32:58 -08007402 // If we can't identify the process or it's already exceeded its crash quota,
7403 // quit right away without showing a crash dialog.
7404 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007405 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007406 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007407 }
7408
7409 Message msg = Message.obtain();
7410 msg.what = SHOW_ERROR_MSG;
7411 HashMap data = new HashMap();
7412 data.put("result", result);
7413 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007414 msg.obj = data;
7415 mHandler.sendMessage(msg);
7416
7417 Binder.restoreCallingIdentity(origId);
7418 }
7419
7420 int res = result.get();
7421
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007422 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007423 synchronized (this) {
7424 if (r != null) {
7425 mProcessCrashTimes.put(r.info.processName, r.info.uid,
7426 SystemClock.uptimeMillis());
7427 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007428 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007429 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007430 }
7431 }
7432
7433 if (appErrorIntent != null) {
7434 try {
7435 mContext.startActivity(appErrorIntent);
7436 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007437 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007438 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007439 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007440 }
Dan Egnorb7f03672009-12-09 16:22:32 -08007441
7442 Intent createAppErrorIntentLocked(ProcessRecord r,
7443 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
7444 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007445 if (report == null) {
7446 return null;
7447 }
7448 Intent result = new Intent(Intent.ACTION_APP_ERROR);
7449 result.setComponent(r.errorReportReceiver);
7450 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
7451 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
7452 return result;
7453 }
7454
Dan Egnorb7f03672009-12-09 16:22:32 -08007455 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
7456 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007457 if (r.errorReportReceiver == null) {
7458 return null;
7459 }
7460
7461 if (!r.crashing && !r.notResponding) {
7462 return null;
7463 }
7464
Dan Egnorb7f03672009-12-09 16:22:32 -08007465 ApplicationErrorReport report = new ApplicationErrorReport();
7466 report.packageName = r.info.packageName;
7467 report.installerPackageName = r.errorReportReceiver.getPackageName();
7468 report.processName = r.processName;
7469 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01007470 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007471
Dan Egnorb7f03672009-12-09 16:22:32 -08007472 if (r.crashing) {
7473 report.type = ApplicationErrorReport.TYPE_CRASH;
7474 report.crashInfo = crashInfo;
7475 } else if (r.notResponding) {
7476 report.type = ApplicationErrorReport.TYPE_ANR;
7477 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007478
Dan Egnorb7f03672009-12-09 16:22:32 -08007479 report.anrInfo.activity = r.notRespondingReport.tag;
7480 report.anrInfo.cause = r.notRespondingReport.shortMsg;
7481 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007482 }
7483
Dan Egnorb7f03672009-12-09 16:22:32 -08007484 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007485 }
7486
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007487 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
7488 // assume our apps are happy - lazy create the list
7489 List<ActivityManager.ProcessErrorStateInfo> errList = null;
7490
7491 synchronized (this) {
7492
7493 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007494 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7495 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007496 if ((app.thread != null) && (app.crashing || app.notResponding)) {
7497 // This one's in trouble, so we'll generate a report for it
7498 // crashes are higher priority (in case there's a crash *and* an anr)
7499 ActivityManager.ProcessErrorStateInfo report = null;
7500 if (app.crashing) {
7501 report = app.crashingReport;
7502 } else if (app.notResponding) {
7503 report = app.notRespondingReport;
7504 }
7505
7506 if (report != null) {
7507 if (errList == null) {
7508 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
7509 }
7510 errList.add(report);
7511 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007512 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007513 " crashing = " + app.crashing +
7514 " notResponding = " + app.notResponding);
7515 }
7516 }
7517 }
7518 }
7519
7520 return errList;
7521 }
7522
7523 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
7524 // Lazy instantiation of list
7525 List<ActivityManager.RunningAppProcessInfo> runList = null;
7526 synchronized (this) {
7527 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007528 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7529 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007530 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
7531 // Generate process state info for running application
7532 ActivityManager.RunningAppProcessInfo currApp =
7533 new ActivityManager.RunningAppProcessInfo(app.processName,
7534 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07007535 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007536 if (mHeavyWeightProcess == app) {
Dianne Hackborn482566e2010-09-03 12:51:28 -07007537 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007538 }
Dianne Hackborn42499172010-10-15 18:45:07 -07007539 if (app.persistent) {
7540 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_PERSISTENT;
7541 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007542 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007543 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007544 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
7545 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
7546 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08007547 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
7548 } else if (adj >= HOME_APP_ADJ) {
7549 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
7550 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007551 } else if (adj >= SECONDARY_SERVER_ADJ) {
7552 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007553 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackborn5383f502010-10-22 12:59:20 -07007554 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007555 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
7556 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007557 } else if (adj >= VISIBLE_APP_ADJ) {
7558 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
7559 } else {
7560 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
7561 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007562 currApp.importanceReasonCode = app.adjTypeCode;
7563 if (app.adjSource instanceof ProcessRecord) {
7564 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007565 } else if (app.adjSource instanceof ActivityRecord) {
7566 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007567 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
7568 }
7569 if (app.adjTarget instanceof ComponentName) {
7570 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
7571 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007572 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007573 // + " lru=" + currApp.lru);
7574 if (runList == null) {
7575 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
7576 }
7577 runList.add(currApp);
7578 }
7579 }
7580 }
7581 return runList;
7582 }
7583
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007584 public List<ApplicationInfo> getRunningExternalApplications() {
7585 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
7586 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
7587 if (runningApps != null && runningApps.size() > 0) {
7588 Set<String> extList = new HashSet<String>();
7589 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
7590 if (app.pkgList != null) {
7591 for (String pkg : app.pkgList) {
7592 extList.add(pkg);
7593 }
7594 }
7595 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007596 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007597 for (String pkg : extList) {
7598 try {
7599 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
7600 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
7601 retList.add(info);
7602 }
7603 } catch (RemoteException e) {
7604 }
7605 }
7606 }
7607 return retList;
7608 }
7609
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007610 @Override
7611 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007612 if (checkCallingPermission(android.Manifest.permission.DUMP)
7613 != PackageManager.PERMISSION_GRANTED) {
7614 pw.println("Permission Denial: can't dump ActivityManager from from pid="
7615 + Binder.getCallingPid()
7616 + ", uid=" + Binder.getCallingUid()
7617 + " without permission "
7618 + android.Manifest.permission.DUMP);
7619 return;
7620 }
7621
7622 boolean dumpAll = false;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007623 boolean dumpClient = false;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007624
7625 int opti = 0;
7626 while (opti < args.length) {
7627 String opt = args[opti];
7628 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
7629 break;
7630 }
7631 opti++;
7632 if ("-a".equals(opt)) {
7633 dumpAll = true;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007634 } else if ("-c".equals(opt)) {
7635 dumpClient = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007636 } else if ("-h".equals(opt)) {
7637 pw.println("Activity manager dump options:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007638 pw.println(" [-a] [-c] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007639 pw.println(" cmd may be one of:");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007640 pw.println(" a[ctivities]: activity stack state");
7641 pw.println(" b[roadcasts]: broadcast state");
7642 pw.println(" i[ntents]: pending intent state");
7643 pw.println(" p[rocesses]: process state");
7644 pw.println(" o[om]: out of memory management");
7645 pw.println(" prov[iders]: content provider state");
7646 pw.println(" s[ervices]: service state");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007647 pw.println(" service [COMP_SPEC]: service client-side state");
7648 pw.println(" cmd may also be a COMP_SPEC to dump activities.");
7649 pw.println(" COMP_SPEC may also be a component name (com.foo/.myApp),");
7650 pw.println(" a partial substring in a component name, an");
7651 pw.println(" ActivityRecord hex object identifier, or");
Dianne Hackbornf9302322011-06-14 18:36:14 -07007652 pw.println(" \"all\" for all objects, or");
7653 pw.println(" \"top\" for the top activity.");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007654 pw.println(" -a: include all available server state.");
7655 pw.println(" -c: include client state.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007656 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007657 } else {
7658 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007659 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007660 }
7661
7662 // Is the caller requesting to dump a particular piece of data?
7663 if (opti < args.length) {
7664 String cmd = args[opti];
7665 opti++;
7666 if ("activities".equals(cmd) || "a".equals(cmd)) {
7667 synchronized (this) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007668 dumpActivitiesLocked(fd, pw, args, opti, true, dumpClient);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007669 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007670 return;
7671 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
7672 synchronized (this) {
7673 dumpBroadcastsLocked(fd, pw, args, opti, true);
7674 }
7675 return;
7676 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
7677 synchronized (this) {
7678 dumpPendingIntentsLocked(fd, pw, args, opti, true);
7679 }
7680 return;
7681 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
7682 synchronized (this) {
7683 dumpProcessesLocked(fd, pw, args, opti, true);
7684 }
7685 return;
Dianne Hackborn287952c2010-09-22 22:34:31 -07007686 } else if ("oom".equals(cmd) || "o".equals(cmd)) {
7687 synchronized (this) {
7688 dumpOomLocked(fd, pw, args, opti, true);
7689 }
7690 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007691 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
7692 synchronized (this) {
7693 dumpProvidersLocked(fd, pw, args, opti, true);
7694 }
7695 return;
7696 } else if ("service".equals(cmd)) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007697 String[] newArgs;
7698 String name;
7699 if (opti >= args.length) {
7700 name = null;
7701 newArgs = EMPTY_STRING_ARRAY;
7702 } else {
7703 name = args[opti];
7704 opti++;
7705 newArgs = new String[args.length - opti];
7706 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
7707 }
7708 if (!dumpService(fd, pw, name, newArgs, 0, dumpAll)) {
7709 pw.println("No services match: " + name);
7710 pw.println("Use -h for help.");
7711 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007712 return;
7713 } else if ("services".equals(cmd) || "s".equals(cmd)) {
7714 synchronized (this) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007715 dumpServicesLocked(fd, pw, args, opti, true, dumpClient);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007716 }
7717 return;
Dianne Hackborn625ac272010-09-17 18:29:22 -07007718 } else {
7719 // Dumping a single activity?
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007720 if (!dumpActivity(fd, pw, cmd, args, opti, dumpAll)) {
7721 pw.println("Bad activity command, or no activities match: " + cmd);
7722 pw.println("Use -h for help.");
Dianne Hackborn625ac272010-09-17 18:29:22 -07007723 }
Dianne Hackborn30d71892010-12-11 10:37:55 -08007724 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007725 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007726 }
7727
7728 // No piece of data specified, dump everything.
7729 synchronized (this) {
7730 boolean needSep;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007731 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007732 if (needSep) {
7733 pw.println(" ");
7734 }
7735 if (dumpAll) {
7736 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007737 }
7738 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
7739 if (needSep) {
7740 pw.println(" ");
7741 }
7742 if (dumpAll) {
7743 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007744 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007745 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007746 if (needSep) {
7747 pw.println(" ");
7748 }
7749 if (dumpAll) {
7750 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007751 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007752 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll, dumpClient);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007753 if (needSep) {
7754 pw.println(" ");
7755 }
7756 if (dumpAll) {
7757 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007758 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007759 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, dumpClient);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007760 if (needSep) {
7761 pw.println(" ");
7762 }
7763 if (dumpAll) {
7764 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007765 }
7766 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
7767 }
7768 }
7769
7770 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007771 int opti, boolean dumpAll, boolean dumpClient) {
7772 pw.println("ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)");
7773 pw.println(" Main stack:");
7774 dumpHistoryList(fd, pw, mMainStack.mHistory, " ", "Hist", true, !dumpAll, dumpClient);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007775 pw.println(" ");
7776 pw.println(" Running activities (most recent first):");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007777 dumpHistoryList(fd, pw, mMainStack.mLRUActivities, " ", "Run", false, !dumpAll, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007778 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007779 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007780 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007781 dumpHistoryList(fd, pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false,
7782 !dumpAll, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007783 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007784 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007785 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007786 pw.println(" Activities waiting to stop:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007787 dumpHistoryList(fd, pw, mMainStack.mStoppingActivities, " ", "Stop", false,
7788 !dumpAll, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007789 }
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08007790 if (mMainStack.mGoingToSleepActivities.size() > 0) {
7791 pw.println(" ");
7792 pw.println(" Activities waiting to sleep:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007793 dumpHistoryList(fd, pw, mMainStack.mGoingToSleepActivities, " ", "Sleep", false,
7794 !dumpAll, false);
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08007795 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007796 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007797 pw.println(" ");
7798 pw.println(" Activities waiting to finish:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007799 dumpHistoryList(fd, pw, mMainStack.mFinishingActivities, " ", "Fin", false,
7800 !dumpAll, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007801 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007802
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007803 pw.println(" ");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007804 if (mMainStack.mPausingActivity != null) {
7805 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
7806 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007807 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007808 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007809 if (dumpAll) {
7810 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
7811 pw.println(" mSleepTimeout: " + mMainStack.mSleepTimeout);
7812 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007813
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007814 if (mRecentTasks.size() > 0) {
7815 pw.println();
7816 pw.println(" Recent tasks:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007817
7818 final int N = mRecentTasks.size();
7819 for (int i=0; i<N; i++) {
7820 TaskRecord tr = mRecentTasks.get(i);
7821 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
7822 pw.println(tr);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007823 if (dumpAll) {
7824 mRecentTasks.get(i).dump(pw, " ");
7825 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007826 }
7827 }
7828
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007829 if (dumpAll) {
7830 pw.println(" ");
7831 pw.println(" mCurTask: " + mCurTask);
7832 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007833
7834 return true;
7835 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07007836
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007837 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7838 int opti, boolean dumpAll) {
7839 boolean needSep = false;
7840 int numPers = 0;
7841
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007842 pw.println("ACTIVITY MANAGER RUNNING PROCESSES (dumpsys activity processes)");
7843
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007844 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007845 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
7846 final int NA = procs.size();
7847 for (int ia=0; ia<NA; ia++) {
7848 if (!needSep) {
7849 pw.println(" All known processes:");
7850 needSep = true;
7851 }
7852 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007853 pw.print(r.persistent ? " *PERS*" : " *APP*");
7854 pw.print(" UID "); pw.print(procs.keyAt(ia));
7855 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007856 r.dump(pw, " ");
7857 if (r.persistent) {
7858 numPers++;
7859 }
7860 }
7861 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007862 }
7863
7864 if (mLruProcesses.size() > 0) {
7865 if (needSep) pw.println(" ");
7866 needSep = true;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007867 pw.println(" Process LRU list (most recent first):");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007868 dumpProcessOomList(pw, this, mLruProcesses, " ",
7869 "Proc", "PERS", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007870 needSep = true;
7871 }
7872
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007873 if (dumpAll) {
7874 synchronized (mPidsSelfLocked) {
7875 if (mPidsSelfLocked.size() > 0) {
7876 if (needSep) pw.println(" ");
7877 needSep = true;
7878 pw.println(" PID mappings:");
7879 for (int i=0; i<mPidsSelfLocked.size(); i++) {
7880 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
7881 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
7882 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007883 }
7884 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007885 }
7886
7887 if (mForegroundProcesses.size() > 0) {
7888 if (needSep) pw.println(" ");
7889 needSep = true;
7890 pw.println(" Foreground Processes:");
7891 for (int i=0; i<mForegroundProcesses.size(); i++) {
7892 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
7893 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007894 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007895 }
7896
7897 if (mPersistentStartingProcesses.size() > 0) {
7898 if (needSep) pw.println(" ");
7899 needSep = true;
7900 pw.println(" Persisent processes that are starting:");
7901 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007902 "Starting Norm", "Restarting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007903 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007904
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007905 if (mRemovedProcesses.size() > 0) {
7906 if (needSep) pw.println(" ");
7907 needSep = true;
7908 pw.println(" Processes that are being removed:");
7909 dumpProcessList(pw, this, mRemovedProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007910 "Removed Norm", "Removed PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007911 }
7912
7913 if (mProcessesOnHold.size() > 0) {
7914 if (needSep) pw.println(" ");
7915 needSep = true;
7916 pw.println(" Processes that are on old until the system is ready:");
7917 dumpProcessList(pw, this, mProcessesOnHold, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007918 "OnHold Norm", "OnHold PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007919 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007920
Dianne Hackborn287952c2010-09-22 22:34:31 -07007921 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007922
7923 if (mProcessCrashTimes.getMap().size() > 0) {
7924 if (needSep) pw.println(" ");
7925 needSep = true;
7926 pw.println(" Time since processes crashed:");
7927 long now = SystemClock.uptimeMillis();
7928 for (Map.Entry<String, SparseArray<Long>> procs
7929 : mProcessCrashTimes.getMap().entrySet()) {
7930 SparseArray<Long> uids = procs.getValue();
7931 final int N = uids.size();
7932 for (int i=0; i<N; i++) {
7933 pw.print(" Process "); pw.print(procs.getKey());
7934 pw.print(" uid "); pw.print(uids.keyAt(i));
7935 pw.print(": last crashed ");
7936 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007937 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007938 }
7939 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007940 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007941
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007942 if (mBadProcesses.getMap().size() > 0) {
7943 if (needSep) pw.println(" ");
7944 needSep = true;
7945 pw.println(" Bad processes:");
7946 for (Map.Entry<String, SparseArray<Long>> procs
7947 : mBadProcesses.getMap().entrySet()) {
7948 SparseArray<Long> uids = procs.getValue();
7949 final int N = uids.size();
7950 for (int i=0; i<N; i++) {
7951 pw.print(" Bad process "); pw.print(procs.getKey());
7952 pw.print(" uid "); pw.print(uids.keyAt(i));
7953 pw.print(": crashed at time ");
7954 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007955 }
7956 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007957 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007958
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007959 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007960 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007961 if (mHeavyWeightProcess != null) {
7962 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7963 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007964 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007965 if (dumpAll) {
7966 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackborn3d0724d2011-05-12 15:39:41 -07007967 if (mCompatModePackages.getPackages().size() > 0) {
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07007968 pw.println(" mScreenCompatPackages:");
7969 for (Map.Entry<String, Integer> entry
7970 : mCompatModePackages.getPackages().entrySet()) {
7971 String pkg = entry.getKey();
7972 int mode = entry.getValue();
7973 pw.print(" "); pw.print(pkg); pw.print(": ");
7974 pw.print(mode); pw.println();
7975 }
Dianne Hackbornaa9d84c2011-05-09 19:00:59 -07007976 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007977 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007978 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
7979 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
7980 || mOrigWaitForDebugger) {
7981 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
7982 + " mDebugTransient=" + mDebugTransient
7983 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
7984 }
7985 if (mAlwaysFinishActivities || mController != null) {
7986 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
7987 + " mController=" + mController);
7988 }
7989 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007990 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007991 pw.println(" mStartRunning=" + mStartRunning
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07007992 + " mProcessesReady=" + mProcessesReady
7993 + " mSystemReady=" + mSystemReady);
7994 pw.println(" mBooting=" + mBooting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007995 + " mBooted=" + mBooted
7996 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn287952c2010-09-22 22:34:31 -07007997 pw.print(" mLastPowerCheckRealtime=");
7998 TimeUtils.formatDuration(mLastPowerCheckRealtime, pw);
7999 pw.println("");
8000 pw.print(" mLastPowerCheckUptime=");
8001 TimeUtils.formatDuration(mLastPowerCheckUptime, pw);
8002 pw.println("");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008003 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
8004 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07008005 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008006 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008007
8008 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008009 }
8010
Dianne Hackborn287952c2010-09-22 22:34:31 -07008011 boolean dumpProcessesToGc(FileDescriptor fd, PrintWriter pw, String[] args,
8012 int opti, boolean needSep, boolean dumpAll) {
8013 if (mProcessesToGc.size() > 0) {
8014 if (needSep) pw.println(" ");
8015 needSep = true;
8016 pw.println(" Processes that are waiting to GC:");
8017 long now = SystemClock.uptimeMillis();
8018 for (int i=0; i<mProcessesToGc.size(); i++) {
8019 ProcessRecord proc = mProcessesToGc.get(i);
8020 pw.print(" Process "); pw.println(proc);
8021 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
8022 pw.print(", last gced=");
8023 pw.print(now-proc.lastRequestedGc);
8024 pw.print(" ms ago, last lowMem=");
8025 pw.print(now-proc.lastLowMemory);
8026 pw.println(" ms ago");
8027
8028 }
8029 }
8030 return needSep;
8031 }
8032
8033 boolean dumpOomLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8034 int opti, boolean dumpAll) {
8035 boolean needSep = false;
8036
8037 if (mLruProcesses.size() > 0) {
8038 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>(mLruProcesses);
8039
8040 Comparator<ProcessRecord> comparator = new Comparator<ProcessRecord>() {
8041 @Override
8042 public int compare(ProcessRecord object1, ProcessRecord object2) {
8043 if (object1.setAdj != object2.setAdj) {
8044 return object1.setAdj > object2.setAdj ? -1 : 1;
8045 }
8046 if (object1.setSchedGroup != object2.setSchedGroup) {
8047 return object1.setSchedGroup > object2.setSchedGroup ? -1 : 1;
8048 }
8049 if (object1.keeping != object2.keeping) {
8050 return object1.keeping ? -1 : 1;
8051 }
8052 if (object1.pid != object2.pid) {
8053 return object1.pid > object2.pid ? -1 : 1;
8054 }
8055 return 0;
8056 }
8057 };
8058
8059 Collections.sort(procs, comparator);
8060
8061 if (needSep) pw.println(" ");
8062 needSep = true;
8063 pw.println(" Process OOM control:");
8064 dumpProcessOomList(pw, this, procs, " ",
8065 "Proc", "PERS", true);
8066 needSep = true;
8067 }
8068
8069 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
8070
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008071 pw.println();
Dianne Hackborn287952c2010-09-22 22:34:31 -07008072 pw.println(" mHomeProcess: " + mHomeProcess);
8073 if (mHeavyWeightProcess != null) {
8074 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
8075 }
8076
8077 return true;
8078 }
8079
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008080 /**
8081 * There are three ways to call this:
8082 * - no service specified: dump all the services
8083 * - a flattened component name that matched an existing service was specified as the
8084 * first arg: dump that one service
8085 * - the first arg isn't the flattened component name of an existing service:
8086 * dump all services whose component contains the first arg as a substring
8087 */
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008088 protected boolean dumpService(FileDescriptor fd, PrintWriter pw, String name, String[] args,
8089 int opti, boolean dumpAll) {
8090 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008091
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008092 if ("all".equals(name)) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07008093 synchronized (this) {
8094 for (ServiceRecord r1 : mServices.values()) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008095 services.add(r1);
8096 }
8097 }
8098 } else {
8099 ComponentName componentName = name != null
8100 ? ComponentName.unflattenFromString(name) : null;
8101 int objectId = 0;
8102 if (componentName == null) {
8103 // Not a '/' separated full component name; maybe an object ID?
8104 try {
8105 objectId = Integer.parseInt(name, 16);
8106 name = null;
8107 componentName = null;
8108 } catch (RuntimeException e) {
8109 }
8110 }
8111
8112 synchronized (this) {
8113 for (ServiceRecord r1 : mServices.values()) {
8114 if (componentName != null) {
8115 if (r1.name.equals(componentName)) {
8116 services.add(r1);
8117 }
8118 } else if (name != null) {
8119 if (r1.name.flattenToString().contains(name)) {
8120 services.add(r1);
8121 }
8122 } else if (System.identityHashCode(r1) == objectId) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07008123 services.add(r1);
8124 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008125 }
8126 }
8127 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008128
8129 if (services.size() <= 0) {
8130 return false;
8131 }
8132
8133 boolean needSep = false;
8134 for (int i=0; i<services.size(); i++) {
8135 if (needSep) {
8136 pw.println();
8137 }
8138 needSep = true;
8139 dumpService("", fd, pw, services.get(i), args, dumpAll);
8140 }
8141 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008142 }
8143
8144 /**
8145 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
8146 * there is a thread associated with the service.
8147 */
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008148 private void dumpService(String prefix, FileDescriptor fd, PrintWriter pw,
8149 final ServiceRecord r, String[] args, boolean dumpAll) {
8150 String innerPrefix = prefix + " ";
8151 synchronized (this) {
8152 pw.print(prefix); pw.print("SERVICE ");
8153 pw.print(r.shortName); pw.print(" ");
8154 pw.print(Integer.toHexString(System.identityHashCode(r)));
8155 pw.print(" pid=");
8156 if (r.app != null) pw.println(r.app.pid);
8157 else pw.println("(not running)");
8158 if (dumpAll) {
8159 r.dump(pw, innerPrefix);
8160 }
8161 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008162 if (r.app != null && r.app.thread != null) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008163 pw.print(prefix); pw.println(" Client:");
8164 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008165 try {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008166 TransferPipe tp = new TransferPipe();
8167 try {
8168 r.app.thread.dumpService(tp.getWriteFd().getFileDescriptor(), r, args);
8169 tp.setBufferPrefix(prefix + " ");
8170 tp.go(fd);
8171 } finally {
8172 tp.kill();
8173 }
8174 } catch (IOException e) {
8175 pw.println(prefix + " Failure while dumping the service: " + e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008176 } catch (RemoteException e) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008177 pw.println(prefix + " Got a RemoteException while dumping the service");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008178 }
8179 }
8180 }
8181
Dianne Hackborn625ac272010-09-17 18:29:22 -07008182 /**
8183 * There are three things that cmd can be:
8184 * - a flattened component name that matched an existing activity
8185 * - the cmd arg isn't the flattened component name of an existing activity:
8186 * dump all activity whose component contains the cmd as a substring
8187 * - A hex number of the ActivityRecord object instance.
8188 */
8189 protected boolean dumpActivity(FileDescriptor fd, PrintWriter pw, String name, String[] args,
8190 int opti, boolean dumpAll) {
Dianne Hackborn625ac272010-09-17 18:29:22 -07008191 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008192
8193 if ("all".equals(name)) {
8194 synchronized (this) {
8195 for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
Dianne Hackborn625ac272010-09-17 18:29:22 -07008196 activities.add(r1);
8197 }
8198 }
Dianne Hackbornf9302322011-06-14 18:36:14 -07008199 } else if ("top".equals(name)) {
8200 synchronized (this) {
8201 final int N = mMainStack.mHistory.size();
8202 if (N > 0) {
8203 activities.add((ActivityRecord)mMainStack.mHistory.get(N-1));
8204 }
8205 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008206 } else {
8207 ComponentName componentName = ComponentName.unflattenFromString(name);
8208 int objectId = 0;
8209 if (componentName == null) {
8210 // Not a '/' separated full component name; maybe an object ID?
8211 try {
8212 objectId = Integer.parseInt(name, 16);
8213 name = null;
8214 componentName = null;
8215 } catch (RuntimeException e) {
8216 }
8217 }
8218
8219 synchronized (this) {
8220 for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
8221 if (componentName != null) {
8222 if (r1.intent.getComponent().equals(componentName)) {
8223 activities.add(r1);
8224 }
8225 } else if (name != null) {
8226 if (r1.intent.getComponent().flattenToString().contains(name)) {
8227 activities.add(r1);
8228 }
8229 } else if (System.identityHashCode(r1) == objectId) {
8230 activities.add(r1);
8231 }
8232 }
8233 }
Dianne Hackborn625ac272010-09-17 18:29:22 -07008234 }
8235
8236 if (activities.size() <= 0) {
8237 return false;
8238 }
8239
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008240 String[] newArgs = new String[args.length - opti];
8241 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
8242
Dianne Hackborn30d71892010-12-11 10:37:55 -08008243 TaskRecord lastTask = null;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008244 boolean needSep = false;
Dianne Hackborn30d71892010-12-11 10:37:55 -08008245 for (int i=activities.size()-1; i>=0; i--) {
8246 ActivityRecord r = (ActivityRecord)activities.get(i);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008247 if (needSep) {
8248 pw.println();
8249 }
8250 needSep = true;
8251 synchronized (this) {
8252 if (lastTask != r.task) {
8253 lastTask = r.task;
8254 pw.print("TASK "); pw.print(lastTask.affinity);
8255 pw.print(" id="); pw.println(lastTask.taskId);
8256 if (dumpAll) {
8257 lastTask.dump(pw, " ");
8258 }
Dianne Hackborn30d71892010-12-11 10:37:55 -08008259 }
8260 }
8261 dumpActivity(" ", fd, pw, activities.get(i), newArgs, dumpAll);
Dianne Hackborn625ac272010-09-17 18:29:22 -07008262 }
8263 return true;
8264 }
8265
8266 /**
8267 * Invokes IApplicationThread.dumpActivity() on the thread of the specified activity if
8268 * there is a thread associated with the activity.
8269 */
Dianne Hackborn30d71892010-12-11 10:37:55 -08008270 private void dumpActivity(String prefix, FileDescriptor fd, PrintWriter pw,
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008271 final ActivityRecord r, String[] args, boolean dumpAll) {
8272 String innerPrefix = prefix + " ";
Dianne Hackborn30d71892010-12-11 10:37:55 -08008273 synchronized (this) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008274 pw.print(prefix); pw.print("ACTIVITY "); pw.print(r.shortComponentName);
8275 pw.print(" "); pw.print(Integer.toHexString(System.identityHashCode(r)));
8276 pw.print(" pid=");
Dianne Hackborn30d71892010-12-11 10:37:55 -08008277 if (r.app != null) pw.println(r.app.pid);
8278 else pw.println("(not running)");
8279 if (dumpAll) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008280 r.dump(pw, innerPrefix);
Dianne Hackborn625ac272010-09-17 18:29:22 -07008281 }
Dianne Hackborn625ac272010-09-17 18:29:22 -07008282 }
8283 if (r.app != null && r.app.thread != null) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008284 // flush anything that is already in the PrintWriter since the thread is going
8285 // to write to the file descriptor directly
8286 pw.flush();
Dianne Hackborn625ac272010-09-17 18:29:22 -07008287 try {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008288 TransferPipe tp = new TransferPipe();
8289 try {
8290 r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(), r,
8291 innerPrefix, args);
8292 tp.go(fd);
8293 } finally {
8294 tp.kill();
8295 }
8296 } catch (IOException e) {
8297 pw.println(innerPrefix + "Failure while dumping the activity: " + e);
Dianne Hackborn625ac272010-09-17 18:29:22 -07008298 } catch (RemoteException e) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008299 pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
Dianne Hackborn625ac272010-09-17 18:29:22 -07008300 }
8301 }
8302 }
8303
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008304 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8305 int opti, boolean dumpAll) {
8306 boolean needSep = false;
8307
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008308 pw.println("ACTIVITY MANAGER BROADCAST STATE (dumpsys activity broadcasts)");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008309 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008310 if (mRegisteredReceivers.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008311 pw.println(" Registered Receivers:");
8312 Iterator it = mRegisteredReceivers.values().iterator();
8313 while (it.hasNext()) {
8314 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008315 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008316 r.dump(pw, " ");
8317 }
8318 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008319
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008320 pw.println();
8321 pw.println(" Receiver Resolver Table:");
8322 mReceiverResolver.dump(pw, null, " ", null, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008323 needSep = true;
8324 }
8325
8326 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
8327 || mPendingBroadcast != null) {
8328 if (mParallelBroadcasts.size() > 0) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008329 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008330 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008331 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008332 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
8333 pw.println(" Broadcast #" + i + ":");
8334 mParallelBroadcasts.get(i).dump(pw, " ");
8335 }
8336 if (mOrderedBroadcasts.size() > 0) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008337 pw.println();
Dianne Hackborn399cccb2010-04-13 22:57:49 -07008338 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008339 }
8340 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
8341 pw.println(" Serialized Broadcast #" + i + ":");
8342 mOrderedBroadcasts.get(i).dump(pw, " ");
8343 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008344 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008345 pw.println(" Pending broadcast:");
8346 if (mPendingBroadcast != null) {
8347 mPendingBroadcast.dump(pw, " ");
8348 } else {
8349 pw.println(" (null)");
8350 }
8351 needSep = true;
8352 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008353
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008354 if (needSep) {
8355 pw.println();
8356 }
8357 pw.println(" Historical broadcasts:");
8358 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
8359 BroadcastRecord r = mBroadcastHistory[i];
8360 if (r == null) {
8361 break;
8362 }
8363 if (dumpAll) {
8364 pw.print(" Historical Broadcast #"); pw.print(i); pw.println(":");
8365 r.dump(pw, " ");
8366 } else {
8367 if (i >= 50) {
8368 pw.println(" ...");
Dianne Hackborn12527f92009-11-11 17:39:50 -08008369 break;
8370 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008371 pw.print(" #"); pw.print(i); pw.print(": "); pw.println(r);
Dianne Hackborn12527f92009-11-11 17:39:50 -08008372 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008373 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008374 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008375
8376 if (mStickyBroadcasts != null) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008377 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008378 pw.println(" Sticky broadcasts:");
8379 StringBuilder sb = new StringBuilder(128);
8380 for (Map.Entry<String, ArrayList<Intent>> ent
8381 : mStickyBroadcasts.entrySet()) {
8382 pw.print(" * Sticky action "); pw.print(ent.getKey());
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008383 if (dumpAll) {
8384 pw.println(":");
8385 ArrayList<Intent> intents = ent.getValue();
8386 final int N = intents.size();
8387 for (int i=0; i<N; i++) {
8388 sb.setLength(0);
8389 sb.append(" Intent: ");
8390 intents.get(i).toShortString(sb, true, false);
8391 pw.println(sb.toString());
8392 Bundle bundle = intents.get(i).getExtras();
8393 if (bundle != null) {
8394 pw.print(" ");
8395 pw.println(bundle.toString());
8396 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008397 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008398 } else {
8399 pw.println("");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008400 }
8401 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008402 needSep = true;
8403 }
8404
8405 if (dumpAll) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008406 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008407 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008408 pw.println(" mHandler:");
8409 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008410 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008411 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008412
8413 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008414 }
8415
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008416 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008417 int opti, boolean dumpAll, boolean dumpClient) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008418 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008419
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008420 pw.println("ACTIVITY MANAGER SERVICES (dumpsys activity services)");
8421 if (mServices.size() > 0) {
8422 pw.println(" Active services:");
8423 long nowReal = SystemClock.elapsedRealtime();
8424 Iterator<ServiceRecord> it = mServices.values().iterator();
8425 needSep = false;
8426 while (it.hasNext()) {
8427 ServiceRecord r = it.next();
8428 if (needSep) {
8429 pw.println();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008430 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008431 pw.print(" * "); pw.println(r);
8432 if (dumpAll) {
8433 r.dump(pw, " ");
8434 needSep = true;
8435 } else {
8436 pw.print(" app="); pw.println(r.app);
8437 pw.print(" created=");
8438 TimeUtils.formatDuration(r.createTime, nowReal, pw);
8439 pw.print(" started="); pw.print(r.startRequested);
8440 pw.print(" connections="); pw.println(r.connections.size());
8441 }
8442 if (dumpClient && r.app != null && r.app.thread != null) {
8443 pw.println(" Client:");
8444 pw.flush();
8445 try {
8446 TransferPipe tp = new TransferPipe();
8447 try {
8448 r.app.thread.dumpService(
8449 tp.getWriteFd().getFileDescriptor(), r, args);
8450 tp.setBufferPrefix(" ");
8451 // Short timeout, since blocking here can
8452 // deadlock with the application.
8453 tp.go(fd, 2000);
8454 } finally {
8455 tp.kill();
8456 }
8457 } catch (IOException e) {
8458 pw.println(" Failure while dumping the service: " + e);
8459 } catch (RemoteException e) {
8460 pw.println(" Got a RemoteException while dumping the service");
8461 }
8462 needSep = true;
8463 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008464 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008465 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008466 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008467
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008468 if (mPendingServices.size() > 0) {
8469 if (needSep) pw.println(" ");
8470 pw.println(" Pending services:");
8471 for (int i=0; i<mPendingServices.size(); i++) {
8472 ServiceRecord r = mPendingServices.get(i);
8473 pw.print(" * Pending "); pw.println(r);
8474 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008475 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008476 needSep = true;
8477 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008478
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008479 if (mRestartingServices.size() > 0) {
8480 if (needSep) pw.println(" ");
8481 pw.println(" Restarting services:");
8482 for (int i=0; i<mRestartingServices.size(); i++) {
8483 ServiceRecord r = mRestartingServices.get(i);
8484 pw.print(" * Restarting "); pw.println(r);
8485 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008486 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008487 needSep = true;
8488 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008489
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008490 if (mStoppingServices.size() > 0) {
8491 if (needSep) pw.println(" ");
8492 pw.println(" Stopping services:");
8493 for (int i=0; i<mStoppingServices.size(); i++) {
8494 ServiceRecord r = mStoppingServices.get(i);
8495 pw.print(" * Stopping "); pw.println(r);
8496 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008497 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008498 needSep = true;
8499 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008500
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008501 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008502 if (mServiceConnections.size() > 0) {
8503 if (needSep) pw.println(" ");
8504 pw.println(" Connection bindings to services:");
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008505 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008506 = mServiceConnections.values().iterator();
8507 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008508 ArrayList<ConnectionRecord> r = it.next();
8509 for (int i=0; i<r.size(); i++) {
8510 pw.print(" * "); pw.println(r.get(i));
8511 r.get(i).dump(pw, " ");
8512 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008513 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008514 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008515 }
8516 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008517
8518 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008519 }
8520
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008521 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8522 int opti, boolean dumpAll) {
8523 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008524
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008525 pw.println("ACTIVITY MANAGER CONTENT PROVIDERS (dumpsys activity providers)");
8526 if (mProvidersByClass.size() > 0) {
8527 if (needSep) pw.println(" ");
8528 pw.println(" Published content providers (by class):");
8529 Iterator<Map.Entry<String, ContentProviderRecord>> it
8530 = mProvidersByClass.entrySet().iterator();
8531 while (it.hasNext()) {
8532 Map.Entry<String, ContentProviderRecord> e = it.next();
8533 ContentProviderRecord r = e.getValue();
8534 if (dumpAll) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008535 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008536 r.dump(pw, " ");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008537 } else {
8538 pw.print(" * "); pw.print(r.name.toShortString());
8539 if (r.app != null) {
8540 pw.println(":");
8541 pw.print(" "); pw.println(r.app);
8542 } else {
8543 pw.println();
8544 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008545 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008546 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008547 needSep = true;
8548 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008549
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008550 if (dumpAll) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008551 if (mProvidersByName.size() > 0) {
8552 pw.println(" ");
8553 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -07008554 Iterator<Map.Entry<String, ContentProviderRecord>> it
8555 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008556 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008557 Map.Entry<String, ContentProviderRecord> e = it.next();
8558 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008559 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
8560 pw.println(r);
8561 }
8562 needSep = true;
8563 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008564 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008565
8566 if (mLaunchingProviders.size() > 0) {
8567 if (needSep) pw.println(" ");
8568 pw.println(" Launching content providers:");
8569 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
8570 pw.print(" Launching #"); pw.print(i); pw.print(": ");
8571 pw.println(mLaunchingProviders.get(i));
8572 }
8573 needSep = true;
8574 }
8575
8576 if (mGrantedUriPermissions.size() > 0) {
8577 pw.println();
8578 pw.println("Granted Uri Permissions:");
8579 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
8580 int uid = mGrantedUriPermissions.keyAt(i);
8581 HashMap<Uri, UriPermission> perms
8582 = mGrantedUriPermissions.valueAt(i);
8583 pw.print(" * UID "); pw.print(uid);
8584 pw.println(" holds:");
8585 for (UriPermission perm : perms.values()) {
8586 pw.print(" "); pw.println(perm);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008587 if (dumpAll) {
8588 perm.dump(pw, " ");
8589 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008590 }
8591 }
8592 needSep = true;
8593 }
8594
8595 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008596 }
8597
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008598 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8599 int opti, boolean dumpAll) {
8600 boolean needSep = false;
8601
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008602 if (this.mIntentSenderRecords.size() > 0) {
8603 pw.println("ACTIVITY MANAGER PENDING INTENTS (dumpsys activity intents)");
8604 Iterator<WeakReference<PendingIntentRecord>> it
8605 = mIntentSenderRecords.values().iterator();
8606 while (it.hasNext()) {
8607 WeakReference<PendingIntentRecord> ref = it.next();
8608 PendingIntentRecord rec = ref != null ? ref.get(): null;
8609 needSep = true;
8610 if (rec != null) {
8611 pw.print(" * "); pw.println(rec);
8612 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008613 rec.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008614 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008615 } else {
8616 pw.print(" * "); pw.println(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008617 }
8618 }
8619 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008620
8621 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008622 }
8623
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008624 private static final void dumpHistoryList(FileDescriptor fd, PrintWriter pw, List list,
8625 String prefix, String label, boolean complete, boolean brief, boolean client) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008626 TaskRecord lastTask = null;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008627 boolean needNL = false;
8628 final String innerPrefix = prefix + " ";
8629 final String[] args = new String[0];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008630 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008631 final ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackbornf26fd992011-04-08 18:14:09 -07008632 final boolean full = !brief && (complete || !r.isInHistory());
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008633 if (needNL) {
8634 pw.println(" ");
8635 needNL = false;
8636 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008637 if (lastTask != r.task) {
8638 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008639 pw.print(prefix);
8640 pw.print(full ? "* " : " ");
8641 pw.println(lastTask);
8642 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008643 lastTask.dump(pw, prefix + " ");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008644 } else if (complete) {
8645 // Complete + brief == give a summary. Isn't that obvious?!?
8646 if (lastTask.intent != null) {
8647 pw.print(prefix); pw.print(" "); pw.println(lastTask.intent);
8648 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008649 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008650 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008651 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
8652 pw.print(" #"); pw.print(i); pw.print(": ");
8653 pw.println(r);
8654 if (full) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008655 r.dump(pw, innerPrefix);
8656 } else if (complete) {
8657 // Complete + brief == give a summary. Isn't that obvious?!?
8658 pw.print(innerPrefix); pw.println(r.intent);
8659 if (r.app != null) {
8660 pw.print(innerPrefix); pw.println(r.app);
8661 }
8662 }
8663 if (client && r.app != null && r.app.thread != null) {
8664 // flush anything that is already in the PrintWriter since the thread is going
8665 // to write to the file descriptor directly
8666 pw.flush();
8667 try {
8668 TransferPipe tp = new TransferPipe();
8669 try {
8670 r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(), r,
8671 innerPrefix, args);
8672 // Short timeout, since blocking here can
8673 // deadlock with the application.
8674 tp.go(fd, 2000);
8675 } finally {
8676 tp.kill();
8677 }
8678 } catch (IOException e) {
8679 pw.println(innerPrefix + "Failure while dumping the activity: " + e);
8680 } catch (RemoteException e) {
8681 pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
8682 }
8683 needNL = true;
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008684 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008685 }
8686 }
8687
Dianne Hackborn09c916b2009-12-08 14:50:51 -08008688 private static String buildOomTag(String prefix, String space, int val, int base) {
8689 if (val == base) {
8690 if (space == null) return prefix;
8691 return prefix + " ";
8692 }
8693 return prefix + "+" + Integer.toString(val-base);
8694 }
8695
8696 private static final int dumpProcessList(PrintWriter pw,
8697 ActivityManagerService service, List list,
Dianne Hackborn287952c2010-09-22 22:34:31 -07008698 String prefix, String normalLabel, String persistentLabel) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008699 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07008700 final int N = list.size()-1;
8701 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008702 ProcessRecord r = (ProcessRecord)list.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008703 pw.println(String.format("%s%s #%2d: %s",
8704 prefix, (r.persistent ? persistentLabel : normalLabel),
8705 i, r.toString()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008706 if (r.persistent) {
8707 numPers++;
8708 }
8709 }
8710 return numPers;
8711 }
8712
Dianne Hackborn287952c2010-09-22 22:34:31 -07008713 private static final void dumpProcessOomList(PrintWriter pw,
8714 ActivityManagerService service, List<ProcessRecord> list,
8715 String prefix, String normalLabel, String persistentLabel,
8716 boolean inclDetails) {
8717
8718 final long curRealtime = SystemClock.elapsedRealtime();
8719 final long realtimeSince = curRealtime - service.mLastPowerCheckRealtime;
8720 final long curUptime = SystemClock.uptimeMillis();
8721 final long uptimeSince = curUptime - service.mLastPowerCheckUptime;
8722
8723 final int N = list.size()-1;
8724 for (int i=N; i>=0; i--) {
8725 ProcessRecord r = list.get(i);
8726 String oomAdj;
8727 if (r.setAdj >= EMPTY_APP_ADJ) {
8728 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
8729 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
8730 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
8731 } else if (r.setAdj >= HOME_APP_ADJ) {
8732 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
8733 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
8734 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
8735 } else if (r.setAdj >= BACKUP_APP_ADJ) {
8736 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
8737 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
8738 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
8739 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
8740 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
8741 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
8742 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
8743 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
8744 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
8745 } else if (r.setAdj >= CORE_SERVER_ADJ) {
8746 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
8747 } else if (r.setAdj >= SYSTEM_ADJ) {
8748 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
8749 } else {
8750 oomAdj = Integer.toString(r.setAdj);
8751 }
8752 String schedGroup;
8753 switch (r.setSchedGroup) {
8754 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
8755 schedGroup = "B";
8756 break;
8757 case Process.THREAD_GROUP_DEFAULT:
8758 schedGroup = "F";
8759 break;
8760 default:
8761 schedGroup = Integer.toString(r.setSchedGroup);
8762 break;
8763 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07008764 String foreground;
8765 if (r.foregroundActivities) {
8766 foreground = "A";
8767 } else if (r.foregroundServices) {
8768 foreground = "S";
8769 } else {
8770 foreground = " ";
8771 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -07008772 pw.println(String.format("%s%s #%2d: adj=%s/%s%s trm=%2d %s (%s)",
Dianne Hackborn287952c2010-09-22 22:34:31 -07008773 prefix, (r.persistent ? persistentLabel : normalLabel),
Dianne Hackbornce86ba82011-07-13 19:33:41 -07008774 N-i, oomAdj, schedGroup, foreground, r.trimMemoryLevel,
8775 r.toShortString(), r.adjType));
Dianne Hackborn287952c2010-09-22 22:34:31 -07008776 if (r.adjSource != null || r.adjTarget != null) {
8777 pw.print(prefix);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008778 pw.print(" ");
Dianne Hackborn287952c2010-09-22 22:34:31 -07008779 if (r.adjTarget instanceof ComponentName) {
8780 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
8781 } else if (r.adjTarget != null) {
8782 pw.print(r.adjTarget.toString());
8783 } else {
8784 pw.print("{null}");
8785 }
8786 pw.print("<=");
8787 if (r.adjSource instanceof ProcessRecord) {
8788 pw.print("Proc{");
8789 pw.print(((ProcessRecord)r.adjSource).toShortString());
8790 pw.println("}");
8791 } else if (r.adjSource != null) {
8792 pw.println(r.adjSource.toString());
8793 } else {
8794 pw.println("{null}");
8795 }
8796 }
8797 if (inclDetails) {
8798 pw.print(prefix);
8799 pw.print(" ");
8800 pw.print("oom: max="); pw.print(r.maxAdj);
8801 pw.print(" hidden="); pw.print(r.hiddenAdj);
8802 pw.print(" curRaw="); pw.print(r.curRawAdj);
8803 pw.print(" setRaw="); pw.print(r.setRawAdj);
8804 pw.print(" cur="); pw.print(r.curAdj);
8805 pw.print(" set="); pw.println(r.setAdj);
8806 pw.print(prefix);
8807 pw.print(" ");
8808 pw.print("keeping="); pw.print(r.keeping);
8809 pw.print(" hidden="); pw.print(r.hidden);
8810 pw.print(" empty="); pw.println(r.empty);
8811
8812 if (!r.keeping) {
8813 if (r.lastWakeTime != 0) {
8814 long wtime;
8815 BatteryStatsImpl stats = service.mBatteryStatsService.getActiveStatistics();
8816 synchronized (stats) {
8817 wtime = stats.getProcessWakeTime(r.info.uid,
8818 r.pid, curRealtime);
8819 }
8820 long timeUsed = wtime - r.lastWakeTime;
8821 pw.print(prefix);
8822 pw.print(" ");
8823 pw.print("keep awake over ");
8824 TimeUtils.formatDuration(realtimeSince, pw);
8825 pw.print(" used ");
8826 TimeUtils.formatDuration(timeUsed, pw);
8827 pw.print(" (");
8828 pw.print((timeUsed*100)/realtimeSince);
8829 pw.println("%)");
8830 }
8831 if (r.lastCpuTime != 0) {
8832 long timeUsed = r.curCpuTime - r.lastCpuTime;
8833 pw.print(prefix);
8834 pw.print(" ");
8835 pw.print("run cpu over ");
8836 TimeUtils.formatDuration(uptimeSince, pw);
8837 pw.print(" used ");
8838 TimeUtils.formatDuration(timeUsed, pw);
8839 pw.print(" (");
8840 pw.print((timeUsed*100)/uptimeSince);
8841 pw.println("%)");
8842 }
8843 }
8844 }
8845 }
8846 }
8847
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008848 ArrayList<ProcessRecord> collectProcesses(PrintWriter pw, String[] args) {
8849 ArrayList<ProcessRecord> procs;
8850 synchronized (this) {
8851 if (args != null && args.length > 0
8852 && args[0].charAt(0) != '-') {
8853 procs = new ArrayList<ProcessRecord>();
8854 int pid = -1;
8855 try {
8856 pid = Integer.parseInt(args[0]);
8857 } catch (NumberFormatException e) {
8858
8859 }
8860 for (int i=mLruProcesses.size()-1; i>=0; i--) {
8861 ProcessRecord proc = mLruProcesses.get(i);
8862 if (proc.pid == pid) {
8863 procs.add(proc);
8864 } else if (proc.processName.equals(args[0])) {
8865 procs.add(proc);
8866 }
8867 }
8868 if (procs.size() <= 0) {
8869 pw.println("No process found for: " + args[0]);
8870 return null;
8871 }
8872 } else {
8873 procs = new ArrayList<ProcessRecord>(mLruProcesses);
8874 }
8875 }
8876 return procs;
8877 }
8878
8879 final void dumpGraphicsHardwareUsage(FileDescriptor fd,
8880 PrintWriter pw, String[] args) {
8881 ArrayList<ProcessRecord> procs = collectProcesses(pw, args);
8882 if (procs == null) {
8883 return;
8884 }
8885
8886 long uptime = SystemClock.uptimeMillis();
8887 long realtime = SystemClock.elapsedRealtime();
8888 pw.println("Applications Graphics Acceleration Info:");
8889 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
8890
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008891 for (int i = procs.size() - 1 ; i >= 0 ; i--) {
8892 ProcessRecord r = procs.get(i);
Chet Haase9c1e23b2011-03-24 10:51:31 -07008893 if (r.thread != null) {
8894 pw.println("\n** Graphics info for pid " + r.pid + " [" + r.processName + "] **");
8895 pw.flush();
8896 try {
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07008897 TransferPipe tp = new TransferPipe();
8898 try {
8899 r.thread.dumpGfxInfo(tp.getWriteFd().getFileDescriptor(), args);
8900 tp.go(fd);
8901 } finally {
8902 tp.kill();
8903 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008904 } catch (IOException e) {
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07008905 pw.println("Failure while dumping the app: " + r);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008906 pw.flush();
Chet Haase9c1e23b2011-03-24 10:51:31 -07008907 } catch (RemoteException e) {
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07008908 pw.println("Got a RemoteException while dumping the app " + r);
Chet Haase9c1e23b2011-03-24 10:51:31 -07008909 pw.flush();
8910 }
8911 }
8912 }
Chet Haase9c1e23b2011-03-24 10:51:31 -07008913 }
8914
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07008915 final static class MemItem {
8916 final String label;
8917 final long pss;
8918
8919 public MemItem(String _label, long _pss) {
8920 label = _label;
8921 pss = _pss;
8922 }
8923 }
8924
8925 final void dumpMemItems(PrintWriter pw, String prefix, ArrayList<MemItem> items) {
8926 Collections.sort(items, new Comparator<MemItem>() {
8927 @Override
8928 public int compare(MemItem lhs, MemItem rhs) {
8929 if (lhs.pss < rhs.pss) {
8930 return 1;
8931 } else if (lhs.pss > rhs.pss) {
8932 return -1;
8933 }
8934 return 0;
8935 }
8936 });
8937
8938 for (int i=0; i<items.size(); i++) {
8939 MemItem mi = items.get(i);
8940 pw.print(prefix); pw.printf("%8d Kb: ", mi.pss); pw.println(mi.label);
8941 }
8942 }
8943
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008944 final void dumpApplicationMemoryUsage(FileDescriptor fd,
8945 PrintWriter pw, String prefix, String[] args) {
8946 ArrayList<ProcessRecord> procs = collectProcesses(pw, args);
8947 if (procs == null) {
8948 return;
8949 }
8950
Dianne Hackborn6447ca32009-04-07 19:50:08 -07008951 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008952 long uptime = SystemClock.uptimeMillis();
8953 long realtime = SystemClock.elapsedRealtime();
8954
8955 if (isCheckinRequest) {
8956 // short checkin version
8957 pw.println(uptime + "," + realtime);
8958 pw.flush();
8959 } else {
8960 pw.println("Applications Memory Usage (kB):");
8961 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
8962 }
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07008963
8964 ArrayList<MemItem> procMems = new ArrayList<MemItem>();
8965 long nativePss=0, dalvikPss=0, otherPss=0;
8966 long[] miscPss = new long[Debug.MemoryInfo.NUM_OTHER_STATS];
8967
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008968 for (int i = procs.size() - 1 ; i >= 0 ; i--) {
8969 ProcessRecord r = procs.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008970 if (r.thread != null) {
8971 if (!isCheckinRequest) {
8972 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
8973 pw.flush();
8974 }
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07008975 Debug.MemoryInfo mi = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008976 try {
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07008977 mi = r.thread.dumpMemInfo(fd, args);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008978 } catch (RemoteException e) {
8979 if (!isCheckinRequest) {
8980 pw.println("Got RemoteException!");
8981 pw.flush();
8982 }
8983 }
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07008984 if (!isCheckinRequest && mi != null) {
8985 procMems.add(new MemItem(r.processName + " (pid " + r.pid + ")",
8986 mi.getTotalPss()));
8987
8988 nativePss += mi.nativePss;
8989 dalvikPss += mi.dalvikPss;
8990 otherPss += mi.otherPss;
8991 for (int j=0; j<Debug.MemoryInfo.NUM_OTHER_STATS; j++) {
8992 long mem = mi.getOtherPss(j);
8993 miscPss[j] += mem;
8994 otherPss -= mem;
8995 }
8996 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008997 }
8998 }
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07008999
9000 if (!isCheckinRequest && procs.size() > 1) {
9001 ArrayList<MemItem> catMems = new ArrayList<MemItem>();
9002
9003 catMems.add(new MemItem("Native", nativePss));
9004 catMems.add(new MemItem("Dalvik", dalvikPss));
9005 catMems.add(new MemItem("Unknown", otherPss));
9006 for (int j=0; j<Debug.MemoryInfo.NUM_OTHER_STATS; j++) {
9007 catMems.add(new MemItem(Debug.MemoryInfo.getOtherLabel(j), miscPss[j]));
9008 }
9009
9010 pw.println();
9011 pw.println("Total PSS by process:");
9012 dumpMemItems(pw, " ", procMems);
9013 pw.println();
9014 pw.println("Total PSS by category:");
9015 dumpMemItems(pw, " ", catMems);
9016 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009017 }
9018
9019 /**
9020 * Searches array of arguments for the specified string
9021 * @param args array of argument strings
9022 * @param value value to search for
9023 * @return true if the value is contained in the array
9024 */
9025 private static boolean scanArgs(String[] args, String value) {
9026 if (args != null) {
9027 for (String arg : args) {
9028 if (value.equals(arg)) {
9029 return true;
9030 }
9031 }
9032 }
9033 return false;
9034 }
9035
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009036 private final void killServicesLocked(ProcessRecord app,
9037 boolean allowRestart) {
9038 // Report disconnected services.
9039 if (false) {
9040 // XXX we are letting the client link to the service for
9041 // death notifications.
9042 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009043 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009044 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009045 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009046 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009047 Iterator<ArrayList<ConnectionRecord>> jt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009048 = r.connections.values().iterator();
9049 while (jt.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009050 ArrayList<ConnectionRecord> cl = jt.next();
9051 for (int i=0; i<cl.size(); i++) {
9052 ConnectionRecord c = cl.get(i);
9053 if (c.binding.client != app) {
9054 try {
9055 //c.conn.connected(r.className, null);
9056 } catch (Exception e) {
9057 // todo: this should be asynchronous!
9058 Slog.w(TAG, "Exception thrown disconnected servce "
9059 + r.shortName
9060 + " from app " + app.processName, e);
9061 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009062 }
9063 }
9064 }
9065 }
9066 }
9067 }
9068 }
9069
9070 // Clean up any connections this application has to other services.
9071 if (app.connections.size() > 0) {
9072 Iterator<ConnectionRecord> it = app.connections.iterator();
9073 while (it.hasNext()) {
9074 ConnectionRecord r = it.next();
9075 removeConnectionLocked(r, app, null);
9076 }
9077 }
9078 app.connections.clear();
9079
9080 if (app.services.size() != 0) {
9081 // Any services running in the application need to be placed
9082 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07009083 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009084 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009085 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009086 synchronized (sr.stats.getBatteryStats()) {
9087 sr.stats.stopLaunchedLocked();
9088 }
9089 sr.app = null;
9090 sr.executeNesting = 0;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009091 if (mStoppingServices.remove(sr)) {
9092 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
9093 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009094
9095 boolean hasClients = sr.bindings.size() > 0;
9096 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009097 Iterator<IntentBindRecord> bindings
9098 = sr.bindings.values().iterator();
9099 while (bindings.hasNext()) {
9100 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009101 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009102 + ": shouldUnbind=" + b.hasBound);
9103 b.binder = null;
9104 b.requested = b.received = b.hasBound = false;
9105 }
9106 }
9107
Dianne Hackborn070783f2010-12-29 16:46:28 -08009108 if (sr.crashCount >= 2 && (sr.serviceInfo.applicationInfo.flags
9109 &ApplicationInfo.FLAG_PERSISTENT) == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009110 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009111 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009112 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009113 sr.crashCount, sr.shortName, app.pid);
9114 bringDownServiceLocked(sr, true);
9115 } else if (!allowRestart) {
9116 bringDownServiceLocked(sr, true);
9117 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009118 boolean canceled = scheduleServiceRestartLocked(sr, true);
9119
9120 // Should the service remain running? Note that in the
9121 // extreme case of so many attempts to deliver a command
9122 // that it failed, that we also will stop it here.
9123 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
9124 if (sr.pendingStarts.size() == 0) {
9125 sr.startRequested = false;
9126 if (!hasClients) {
9127 // Whoops, no reason to restart!
9128 bringDownServiceLocked(sr, true);
9129 }
9130 }
9131 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009132 }
9133 }
9134
9135 if (!allowRestart) {
9136 app.services.clear();
9137 }
9138 }
9139
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009140 // Make sure we have no more records on the stopping list.
9141 int i = mStoppingServices.size();
9142 while (i > 0) {
9143 i--;
9144 ServiceRecord sr = mStoppingServices.get(i);
9145 if (sr.app == app) {
9146 mStoppingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009147 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009148 }
9149 }
9150
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009151 app.executingServices.clear();
9152 }
9153
9154 private final void removeDyingProviderLocked(ProcessRecord proc,
9155 ContentProviderRecord cpr) {
9156 synchronized (cpr) {
9157 cpr.launchingApp = null;
9158 cpr.notifyAll();
9159 }
9160
9161 mProvidersByClass.remove(cpr.info.name);
9162 String names[] = cpr.info.authority.split(";");
9163 for (int j = 0; j < names.length; j++) {
9164 mProvidersByName.remove(names[j]);
9165 }
9166
9167 Iterator<ProcessRecord> cit = cpr.clients.iterator();
9168 while (cit.hasNext()) {
9169 ProcessRecord capp = cit.next();
9170 if (!capp.persistent && capp.thread != null
9171 && capp.pid != 0
9172 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07009173 Slog.i(TAG, "Kill " + capp.processName
9174 + " (pid " + capp.pid + "): provider " + cpr.info.name
9175 + " in dying process " + proc.processName);
9176 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
9177 capp.processName, capp.setAdj, "dying provider " + proc.processName);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07009178 Process.killProcessQuiet(capp.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009179 }
9180 }
9181
9182 mLaunchingProviders.remove(cpr);
9183 }
9184
9185 /**
9186 * Main code for cleaning up a process when it has gone away. This is
9187 * called both as a result of the process dying, or directly when stopping
9188 * a process when running in single process mode.
9189 */
9190 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
9191 boolean restarting, int index) {
9192 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009193 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009194 }
9195
Dianne Hackborn36124872009-10-08 16:22:03 -07009196 mProcessesToGc.remove(app);
9197
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009198 // Dismiss any open dialogs.
9199 if (app.crashDialog != null) {
9200 app.crashDialog.dismiss();
9201 app.crashDialog = null;
9202 }
9203 if (app.anrDialog != null) {
9204 app.anrDialog.dismiss();
9205 app.anrDialog = null;
9206 }
9207 if (app.waitDialog != null) {
9208 app.waitDialog.dismiss();
9209 app.waitDialog = null;
9210 }
9211
9212 app.crashing = false;
9213 app.notResponding = false;
9214
9215 app.resetPackageList();
Dianne Hackborn1b64e0d2011-07-17 15:23:59 -07009216 app.unlinkDeathRecipient();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009217 app.thread = null;
9218 app.forcingToForeground = null;
9219 app.foregroundServices = false;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07009220 app.foregroundActivities = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009221
9222 killServicesLocked(app, true);
9223
9224 boolean restart = false;
9225
9226 int NL = mLaunchingProviders.size();
9227
9228 // Remove published content providers.
9229 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009230 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009231 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009232 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009233 cpr.provider = null;
9234 cpr.app = null;
9235
9236 // See if someone is waiting for this provider... in which
9237 // case we don't remove it, but just let it restart.
9238 int i = 0;
9239 if (!app.bad) {
9240 for (; i<NL; i++) {
9241 if (mLaunchingProviders.get(i) == cpr) {
9242 restart = true;
9243 break;
9244 }
9245 }
9246 } else {
9247 i = NL;
9248 }
9249
9250 if (i >= NL) {
9251 removeDyingProviderLocked(app, cpr);
9252 NL = mLaunchingProviders.size();
9253 }
9254 }
9255 app.pubProviders.clear();
9256 }
9257
Dianne Hackbornf670ef72009-11-16 13:59:16 -08009258 // Take care of any launching providers waiting for this process.
9259 if (checkAppInLaunchingProvidersLocked(app, false)) {
9260 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009261 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08009262
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009263 // Unregister from connected content providers.
9264 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07009265 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009266 while (it.hasNext()) {
9267 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
9268 cpr.clients.remove(app);
9269 }
9270 app.conProviders.clear();
9271 }
9272
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009273 // At this point there may be remaining entries in mLaunchingProviders
9274 // where we were the only one waiting, so they are no longer of use.
9275 // Look for these and clean up if found.
9276 // XXX Commented out for now. Trying to figure out a way to reproduce
9277 // the actual situation to identify what is actually going on.
9278 if (false) {
9279 for (int i=0; i<NL; i++) {
9280 ContentProviderRecord cpr = (ContentProviderRecord)
9281 mLaunchingProviders.get(i);
9282 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
9283 synchronized (cpr) {
9284 cpr.launchingApp = null;
9285 cpr.notifyAll();
9286 }
9287 }
9288 }
9289 }
9290
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009291 skipCurrentReceiverLocked(app);
9292
9293 // Unregister any receivers.
9294 if (app.receivers.size() > 0) {
9295 Iterator<ReceiverList> it = app.receivers.iterator();
9296 while (it.hasNext()) {
9297 removeReceiverLocked(it.next());
9298 }
9299 app.receivers.clear();
9300 }
9301
Christopher Tate181fafa2009-05-14 11:12:14 -07009302 // If the app is undergoing backup, tell the backup manager about it
9303 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009304 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -07009305 try {
9306 IBackupManager bm = IBackupManager.Stub.asInterface(
9307 ServiceManager.getService(Context.BACKUP_SERVICE));
9308 bm.agentDisconnected(app.info.packageName);
9309 } catch (RemoteException e) {
9310 // can't happen; backup manager is local
9311 }
9312 }
9313
Jeff Sharkey287bd832011-05-28 19:36:26 -07009314 mHandler.obtainMessage(DISPATCH_PROCESS_DIED, app.pid, app.info.uid, null).sendToTarget();
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07009315
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009316 // If the caller is restarting this app, then leave it in its
9317 // current lists and let the caller take care of it.
9318 if (restarting) {
9319 return;
9320 }
9321
9322 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009323 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009324 "Removing non-persistent process during cleanup: " + app);
9325 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07009326 if (mHeavyWeightProcess == app) {
9327 mHeavyWeightProcess = null;
9328 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
9329 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009330 } else if (!app.removed) {
9331 // This app is persistent, so we need to keep its record around.
9332 // If it is not already on the pending app list, add it there
9333 // and start a new process for it.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009334 app.forcingToForeground = null;
9335 app.foregroundServices = false;
9336 if (mPersistentStartingProcesses.indexOf(app) < 0) {
9337 mPersistentStartingProcesses.add(app);
9338 restart = true;
9339 }
9340 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07009341 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
9342 "Clean-up removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009343 mProcessesOnHold.remove(app);
9344
The Android Open Source Project4df24232009-03-05 14:34:35 -08009345 if (app == mHomeProcess) {
9346 mHomeProcess = null;
9347 }
9348
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009349 if (restart) {
9350 // We have components that still need to be running in the
9351 // process, so re-launch it.
9352 mProcessNames.put(app.processName, app.info.uid, app);
9353 startProcessLocked(app, "restart", app.processName);
9354 } else if (app.pid > 0 && app.pid != MY_PID) {
9355 // Goodbye!
9356 synchronized (mPidsSelfLocked) {
9357 mPidsSelfLocked.remove(app.pid);
9358 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
9359 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009360 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009361 }
9362 }
9363
Dianne Hackbornf670ef72009-11-16 13:59:16 -08009364 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
9365 // Look through the content providers we are waiting to have launched,
9366 // and if any run in this process then either schedule a restart of
9367 // the process or kill the client waiting for it if this process has
9368 // gone bad.
9369 int NL = mLaunchingProviders.size();
9370 boolean restart = false;
9371 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009372 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08009373 if (cpr.launchingApp == app) {
9374 if (!alwaysBad && !app.bad) {
9375 restart = true;
9376 } else {
9377 removeDyingProviderLocked(app, cpr);
9378 NL = mLaunchingProviders.size();
9379 }
9380 }
9381 }
9382 return restart;
9383 }
9384
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009385 // =========================================================
9386 // SERVICES
9387 // =========================================================
9388
9389 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
9390 ActivityManager.RunningServiceInfo info =
9391 new ActivityManager.RunningServiceInfo();
9392 info.service = r.name;
9393 if (r.app != null) {
9394 info.pid = r.app.pid;
9395 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -07009396 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009397 info.process = r.processName;
9398 info.foreground = r.isForeground;
9399 info.activeSince = r.createTime;
9400 info.started = r.startRequested;
9401 info.clientCount = r.connections.size();
9402 info.crashCount = r.crashCount;
9403 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07009404 if (r.isForeground) {
9405 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
9406 }
9407 if (r.startRequested) {
9408 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
9409 }
Dan Egnor42471dd2010-01-07 17:25:22 -08009410 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -07009411 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
9412 }
9413 if (r.app != null && r.app.persistent) {
9414 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
9415 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009416
9417 for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
9418 for (int i=0; i<connl.size(); i++) {
9419 ConnectionRecord conn = connl.get(i);
9420 if (conn.clientLabel != 0) {
9421 info.clientPackage = conn.binding.client.info.packageName;
9422 info.clientLabel = conn.clientLabel;
9423 return info;
9424 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009425 }
9426 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009427 return info;
9428 }
9429
9430 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
9431 int flags) {
9432 synchronized (this) {
9433 ArrayList<ActivityManager.RunningServiceInfo> res
9434 = new ArrayList<ActivityManager.RunningServiceInfo>();
9435
9436 if (mServices.size() > 0) {
9437 Iterator<ServiceRecord> it = mServices.values().iterator();
9438 while (it.hasNext() && res.size() < maxNum) {
9439 res.add(makeRunningServiceInfoLocked(it.next()));
9440 }
9441 }
9442
9443 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
9444 ServiceRecord r = mRestartingServices.get(i);
9445 ActivityManager.RunningServiceInfo info =
9446 makeRunningServiceInfoLocked(r);
9447 info.restarting = r.nextRestartTime;
9448 res.add(info);
9449 }
9450
9451 return res;
9452 }
9453 }
9454
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009455 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
9456 synchronized (this) {
9457 ServiceRecord r = mServices.get(name);
9458 if (r != null) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009459 for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
9460 for (int i=0; i<conn.size(); i++) {
9461 if (conn.get(i).clientIntent != null) {
9462 return conn.get(i).clientIntent;
9463 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009464 }
9465 }
9466 }
9467 }
9468 return null;
9469 }
9470
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009471 private final ServiceRecord findServiceLocked(ComponentName name,
9472 IBinder token) {
9473 ServiceRecord r = mServices.get(name);
9474 return r == token ? r : null;
9475 }
9476
9477 private final class ServiceLookupResult {
9478 final ServiceRecord record;
9479 final String permission;
9480
9481 ServiceLookupResult(ServiceRecord _record, String _permission) {
9482 record = _record;
9483 permission = _permission;
9484 }
9485 };
9486
9487 private ServiceLookupResult findServiceLocked(Intent service,
9488 String resolvedType) {
9489 ServiceRecord r = null;
9490 if (service.getComponent() != null) {
9491 r = mServices.get(service.getComponent());
9492 }
9493 if (r == null) {
9494 Intent.FilterComparison filter = new Intent.FilterComparison(service);
9495 r = mServicesByIntent.get(filter);
9496 }
9497
9498 if (r == null) {
9499 try {
9500 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009501 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009502 service, resolvedType, 0);
9503 ServiceInfo sInfo =
9504 rInfo != null ? rInfo.serviceInfo : null;
9505 if (sInfo == null) {
9506 return null;
9507 }
9508
9509 ComponentName name = new ComponentName(
9510 sInfo.applicationInfo.packageName, sInfo.name);
9511 r = mServices.get(name);
9512 } catch (RemoteException ex) {
9513 // pm is in same process, this will never happen.
9514 }
9515 }
9516 if (r != null) {
9517 int callingPid = Binder.getCallingPid();
9518 int callingUid = Binder.getCallingUid();
9519 if (checkComponentPermission(r.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009520 callingPid, callingUid, r.appInfo.uid, r.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009521 != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009522 if (!r.exported) {
9523 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
9524 + " from pid=" + callingPid
9525 + ", uid=" + callingUid
9526 + " that is not exported from uid " + r.appInfo.uid);
9527 return new ServiceLookupResult(null, "not exported from uid "
9528 + r.appInfo.uid);
9529 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009530 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009531 + " from pid=" + callingPid
9532 + ", uid=" + callingUid
9533 + " requires " + r.permission);
9534 return new ServiceLookupResult(null, r.permission);
9535 }
9536 return new ServiceLookupResult(r, null);
9537 }
9538 return null;
9539 }
9540
9541 private class ServiceRestarter implements Runnable {
9542 private ServiceRecord mService;
9543
9544 void setService(ServiceRecord service) {
9545 mService = service;
9546 }
9547
9548 public void run() {
9549 synchronized(ActivityManagerService.this) {
9550 performServiceRestartLocked(mService);
9551 }
9552 }
9553 }
9554
9555 private ServiceLookupResult retrieveServiceLocked(Intent service,
9556 String resolvedType, int callingPid, int callingUid) {
9557 ServiceRecord r = null;
9558 if (service.getComponent() != null) {
9559 r = mServices.get(service.getComponent());
9560 }
9561 Intent.FilterComparison filter = new Intent.FilterComparison(service);
9562 r = mServicesByIntent.get(filter);
9563 if (r == null) {
9564 try {
9565 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009566 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -07009567 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009568 ServiceInfo sInfo =
9569 rInfo != null ? rInfo.serviceInfo : null;
9570 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009571 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009572 ": not found");
9573 return null;
9574 }
9575
9576 ComponentName name = new ComponentName(
9577 sInfo.applicationInfo.packageName, sInfo.name);
9578 r = mServices.get(name);
9579 if (r == null) {
9580 filter = new Intent.FilterComparison(service.cloneFilter());
9581 ServiceRestarter res = new ServiceRestarter();
9582 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
9583 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
9584 synchronized (stats) {
9585 ss = stats.getServiceStatsLocked(
9586 sInfo.applicationInfo.uid, sInfo.packageName,
9587 sInfo.name);
9588 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -08009589 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009590 res.setService(r);
9591 mServices.put(name, r);
9592 mServicesByIntent.put(filter, r);
9593
9594 // Make sure this component isn't in the pending list.
9595 int N = mPendingServices.size();
9596 for (int i=0; i<N; i++) {
9597 ServiceRecord pr = mPendingServices.get(i);
9598 if (pr.name.equals(name)) {
9599 mPendingServices.remove(i);
9600 i--;
9601 N--;
9602 }
9603 }
9604 }
9605 } catch (RemoteException ex) {
9606 // pm is in same process, this will never happen.
9607 }
9608 }
9609 if (r != null) {
9610 if (checkComponentPermission(r.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009611 callingPid, callingUid, r.appInfo.uid, r.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009612 != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009613 if (!r.exported) {
9614 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
9615 + " from pid=" + callingPid
9616 + ", uid=" + callingUid
9617 + " that is not exported from uid " + r.appInfo.uid);
9618 return new ServiceLookupResult(null, "not exported from uid "
9619 + r.appInfo.uid);
9620 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009621 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009622 + " from pid=" + callingPid
9623 + ", uid=" + callingUid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009624 + " requires " + r.permission);
9625 return new ServiceLookupResult(null, r.permission);
9626 }
9627 return new ServiceLookupResult(r, null);
9628 }
9629 return null;
9630 }
9631
Dianne Hackborn287952c2010-09-22 22:34:31 -07009632 private final void bumpServiceExecutingLocked(ServiceRecord r, String why) {
9633 if (DEBUG_SERVICE) Log.v(TAG, ">>> EXECUTING "
9634 + why + " of " + r + " in app " + r.app);
9635 else if (DEBUG_SERVICE_EXECUTING) Log.v(TAG, ">>> EXECUTING "
9636 + why + " of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009637 long now = SystemClock.uptimeMillis();
9638 if (r.executeNesting == 0 && r.app != null) {
9639 if (r.app.executingServices.size() == 0) {
9640 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
9641 msg.obj = r.app;
9642 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
9643 }
9644 r.app.executingServices.add(r);
9645 }
9646 r.executeNesting++;
9647 r.executingStart = now;
9648 }
9649
9650 private final void sendServiceArgsLocked(ServiceRecord r,
9651 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009652 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009653 if (N == 0) {
9654 return;
9655 }
9656
Dianne Hackborn39792d22010-08-19 18:01:52 -07009657 while (r.pendingStarts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009658 try {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009659 ServiceRecord.StartItem si = r.pendingStarts.remove(0);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009660 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
9661 + r + " " + r.intent + " args=" + si.intent);
Dianne Hackborn3a28f222011-03-01 12:25:54 -08009662 if (si.intent == null && N > 1) {
9663 // If somehow we got a dummy null intent in the middle,
9664 // then skip it. DO NOT skip a null intent when it is
9665 // the only one in the list -- this is to support the
9666 // onStartCommand(null) case.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009667 continue;
9668 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009669 si.deliveredTime = SystemClock.uptimeMillis();
9670 r.deliveredStarts.add(si);
9671 si.deliveryCount++;
Dianne Hackborn3a28f222011-03-01 12:25:54 -08009672 if (si.targetPermissionUid >= 0 && si.intent != null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009673 grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
Dianne Hackborn7e269642010-08-25 19:50:20 -07009674 r.packageName, si.intent, si.getUriPermissionsLocked());
Dianne Hackborn39792d22010-08-19 18:01:52 -07009675 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07009676 bumpServiceExecutingLocked(r, "start");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009677 if (!oomAdjusted) {
9678 oomAdjusted = true;
9679 updateOomAdjLocked(r.app);
9680 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009681 int flags = 0;
9682 if (si.deliveryCount > 0) {
9683 flags |= Service.START_FLAG_RETRY;
9684 }
9685 if (si.doneExecutingCount > 0) {
9686 flags |= Service.START_FLAG_REDELIVERY;
9687 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07009688 r.app.thread.scheduleServiceArgs(r, si.taskRemoved, si.id, flags, si.intent);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009689 } catch (RemoteException e) {
9690 // Remote process gone... we'll let the normal cleanup take
9691 // care of this.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009692 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009693 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009694 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009695 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009696 break;
9697 }
9698 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009699 }
9700
9701 private final boolean requestServiceBindingLocked(ServiceRecord r,
9702 IntentBindRecord i, boolean rebind) {
9703 if (r.app == null || r.app.thread == null) {
9704 // If service is not currently running, can't yet bind.
9705 return false;
9706 }
9707 if ((!i.requested || rebind) && i.apps.size() > 0) {
9708 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009709 bumpServiceExecutingLocked(r, "bind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009710 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
9711 if (!rebind) {
9712 i.requested = true;
9713 }
9714 i.hasBound = true;
9715 i.doRebind = false;
9716 } catch (RemoteException e) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009717 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009718 return false;
9719 }
9720 }
9721 return true;
9722 }
9723
9724 private final void requestServiceBindingsLocked(ServiceRecord r) {
9725 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
9726 while (bindings.hasNext()) {
9727 IntentBindRecord i = bindings.next();
9728 if (!requestServiceBindingLocked(r, i, false)) {
9729 break;
9730 }
9731 }
9732 }
9733
9734 private final void realStartServiceLocked(ServiceRecord r,
9735 ProcessRecord app) throws RemoteException {
9736 if (app.thread == null) {
9737 throw new RemoteException();
9738 }
9739
9740 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -07009741 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009742
9743 app.services.add(r);
Dianne Hackborn287952c2010-09-22 22:34:31 -07009744 bumpServiceExecutingLocked(r, "create");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009745 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009746
9747 boolean created = false;
9748 try {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07009749 mStringBuilder.setLength(0);
9750 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009751 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009752 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -07009753 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009754 synchronized (r.stats.getBatteryStats()) {
9755 r.stats.startLaunchedLocked();
9756 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07009757 ensurePackageDexOpt(r.serviceInfo.packageName);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04009758 app.thread.scheduleCreateService(r, r.serviceInfo,
9759 compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo));
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009760 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009761 created = true;
9762 } finally {
9763 if (!created) {
9764 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009765 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009766 }
9767 }
9768
9769 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009770
9771 // If the service is in the started state, and there are no
9772 // pending arguments, then fake up one so its onStartCommand() will
9773 // be called.
9774 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07009775 r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
9776 null, -1));
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009777 }
9778
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009779 sendServiceArgsLocked(r, true);
9780 }
9781
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009782 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
9783 boolean allowCancel) {
9784 boolean canceled = false;
9785
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009786 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009787 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -07009788 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009789
Dianne Hackborn070783f2010-12-29 16:46:28 -08009790 if ((r.serviceInfo.applicationInfo.flags
9791 &ApplicationInfo.FLAG_PERSISTENT) != 0) {
9792 minDuration /= 4;
9793 }
9794
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009795 // Any delivered but not yet finished starts should be put back
9796 // on the pending list.
9797 final int N = r.deliveredStarts.size();
9798 if (N > 0) {
9799 for (int i=N-1; i>=0; i--) {
9800 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
Dianne Hackborn39792d22010-08-19 18:01:52 -07009801 si.removeUriPermissionsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009802 if (si.intent == null) {
9803 // We'll generate this again if needed.
9804 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
9805 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
9806 r.pendingStarts.add(0, si);
9807 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
9808 dur *= 2;
9809 if (minDuration < dur) minDuration = dur;
9810 if (resetTime < dur) resetTime = dur;
9811 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009812 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009813 + r.name);
9814 canceled = true;
9815 }
9816 }
9817 r.deliveredStarts.clear();
9818 }
9819
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009820 r.totalRestartCount++;
9821 if (r.restartDelay == 0) {
9822 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009823 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009824 } else {
9825 // If it has been a "reasonably long time" since the service
9826 // was started, then reset our restart duration back to
9827 // the beginning, so we don't infinitely increase the duration
9828 // on a service that just occasionally gets killed (which is
9829 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009830 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009831 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009832 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009833 } else {
Dianne Hackborn070783f2010-12-29 16:46:28 -08009834 if ((r.serviceInfo.applicationInfo.flags
9835 &ApplicationInfo.FLAG_PERSISTENT) != 0) {
9836 // Services in peristent processes will restart much more
9837 // quickly, since they are pretty important. (Think SystemUI).
9838 r.restartDelay += minDuration/2;
9839 } else {
9840 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
9841 if (r.restartDelay < minDuration) {
9842 r.restartDelay = minDuration;
9843 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009844 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009845 }
9846 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009847
9848 r.nextRestartTime = now + r.restartDelay;
9849
9850 // Make sure that we don't end up restarting a bunch of services
9851 // all at the same time.
9852 boolean repeat;
9853 do {
9854 repeat = false;
9855 for (int i=mRestartingServices.size()-1; i>=0; i--) {
9856 ServiceRecord r2 = mRestartingServices.get(i);
9857 if (r2 != r && r.nextRestartTime
9858 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
9859 && r.nextRestartTime
9860 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
9861 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
9862 r.restartDelay = r.nextRestartTime - now;
9863 repeat = true;
9864 break;
9865 }
9866 }
9867 } while (repeat);
9868
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009869 if (!mRestartingServices.contains(r)) {
9870 mRestartingServices.add(r);
9871 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009872
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009873 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009874
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009875 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009876 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009877 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009878 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009879 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -08009880 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009881 r.shortName, r.restartDelay);
9882
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009883 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009884 }
9885
9886 final void performServiceRestartLocked(ServiceRecord r) {
9887 if (!mRestartingServices.contains(r)) {
9888 return;
9889 }
9890 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
9891 }
9892
9893 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
9894 if (r.restartDelay == 0) {
9895 return false;
9896 }
9897 r.resetRestartCounter();
9898 mRestartingServices.remove(r);
9899 mHandler.removeCallbacks(r.restarter);
9900 return true;
9901 }
9902
9903 private final boolean bringUpServiceLocked(ServiceRecord r,
9904 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009905 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009906 //r.dump(" ");
9907
Dianne Hackborn36124872009-10-08 16:22:03 -07009908 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009909 sendServiceArgsLocked(r, false);
9910 return true;
9911 }
9912
9913 if (!whileRestarting && r.restartDelay > 0) {
9914 // If waiting for a restart, then do nothing.
9915 return true;
9916 }
9917
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009918 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009919
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009920 // We are now bringing the service up, so no longer in the
9921 // restarting state.
9922 mRestartingServices.remove(r);
9923
Dianne Hackborne7f97212011-02-24 14:40:20 -08009924 // Service is now being launched, its package can't be stopped.
9925 try {
9926 AppGlobals.getPackageManager().setPackageStoppedState(
9927 r.packageName, false);
9928 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08009929 } catch (IllegalArgumentException e) {
9930 Slog.w(TAG, "Failed trying to unstop package "
9931 + r.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08009932 }
9933
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009934 final String appName = r.processName;
9935 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
9936 if (app != null && app.thread != null) {
9937 try {
Dianne Hackborn6c418d52011-06-29 14:05:33 -07009938 app.addPackage(r.appInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009939 realStartServiceLocked(r, app);
9940 return true;
9941 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009942 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009943 }
9944
9945 // If a dead object exception was thrown -- fall through to
9946 // restart the application.
9947 }
9948
Dianne Hackborn36124872009-10-08 16:22:03 -07009949 // Not running -- get it started, and enqueue this service record
9950 // to be executed when the app comes up.
9951 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
9952 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009953 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -07009954 + r.appInfo.packageName + "/"
9955 + r.appInfo.uid + " for service "
9956 + r.intent.getIntent() + ": process is bad");
9957 bringDownServiceLocked(r, true);
9958 return false;
9959 }
9960
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009961 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009962 mPendingServices.add(r);
9963 }
Dianne Hackborn36124872009-10-08 16:22:03 -07009964
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009965 return true;
9966 }
9967
9968 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009969 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009970 //r.dump(" ");
9971
9972 // Does it still need to run?
9973 if (!force && r.startRequested) {
9974 return;
9975 }
9976 if (r.connections.size() > 0) {
9977 if (!force) {
9978 // XXX should probably keep a count of the number of auto-create
9979 // connections directly in the service.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009980 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009981 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009982 ArrayList<ConnectionRecord> cr = it.next();
9983 for (int i=0; i<cr.size(); i++) {
9984 if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
9985 return;
9986 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009987 }
9988 }
9989 }
9990
9991 // Report to all of the connections that the service is no longer
9992 // available.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009993 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009994 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009995 ArrayList<ConnectionRecord> c = it.next();
9996 for (int i=0; i<c.size(); i++) {
9997 try {
9998 c.get(i).conn.connected(r.name, null);
9999 } catch (Exception e) {
10000 Slog.w(TAG, "Failure disconnecting service " + r.name +
10001 " to connection " + c.get(i).conn.asBinder() +
10002 " (in " + c.get(i).binding.client.processName + ")", e);
10003 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010004 }
10005 }
10006 }
10007
10008 // Tell the service that it has been unbound.
10009 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
10010 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
10011 while (it.hasNext()) {
10012 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010013 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010014 + ": hasBound=" + ibr.hasBound);
10015 if (r.app != null && r.app.thread != null && ibr.hasBound) {
10016 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010017 bumpServiceExecutingLocked(r, "bring down unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010018 updateOomAdjLocked(r.app);
10019 ibr.hasBound = false;
10020 r.app.thread.scheduleUnbindService(r,
10021 ibr.intent.getIntent());
10022 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010023 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010024 + r.shortName, e);
10025 serviceDoneExecutingLocked(r, true);
10026 }
10027 }
10028 }
10029 }
10030
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010031 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010032 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010033 System.identityHashCode(r), r.shortName,
10034 (r.app != null) ? r.app.pid : -1);
10035
10036 mServices.remove(r.name);
10037 mServicesByIntent.remove(r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010038 r.totalRestartCount = 0;
10039 unscheduleServiceRestartLocked(r);
10040
10041 // Also make sure it is not on the pending list.
10042 int N = mPendingServices.size();
10043 for (int i=0; i<N; i++) {
10044 if (mPendingServices.get(i) == r) {
10045 mPendingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010046 if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010047 i--;
10048 N--;
10049 }
10050 }
10051
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010052 r.cancelNotification();
10053 r.isForeground = false;
10054 r.foregroundId = 0;
10055 r.foregroundNoti = null;
10056
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010057 // Clear start entries.
Dianne Hackborn39792d22010-08-19 18:01:52 -070010058 r.clearDeliveredStartsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010059 r.pendingStarts.clear();
10060
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010061 if (r.app != null) {
10062 synchronized (r.stats.getBatteryStats()) {
10063 r.stats.stopLaunchedLocked();
10064 }
10065 r.app.services.remove(r);
10066 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010067 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010068 bumpServiceExecutingLocked(r, "stop");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010069 mStoppingServices.add(r);
10070 updateOomAdjLocked(r.app);
10071 r.app.thread.scheduleStopService(r);
10072 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010073 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010074 + r.shortName, e);
10075 serviceDoneExecutingLocked(r, true);
10076 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010077 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010078 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010079 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010080 TAG, "Removed service that has no process: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010081 }
10082 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010083 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010084 TAG, "Removed service that is not running: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010085 }
Vairavan Srinivasana207ce22010-12-23 13:51:48 -080010086
10087 if (r.bindings.size() > 0) {
10088 r.bindings.clear();
10089 }
10090
10091 if (r.restarter instanceof ServiceRestarter) {
10092 ((ServiceRestarter)r.restarter).setService(null);
10093 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010094 }
10095
10096 ComponentName startServiceLocked(IApplicationThread caller,
10097 Intent service, String resolvedType,
10098 int callingPid, int callingUid) {
10099 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010100 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010101 + " type=" + resolvedType + " args=" + service.getExtras());
10102
10103 if (caller != null) {
10104 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10105 if (callerApp == null) {
10106 throw new SecurityException(
10107 "Unable to find app for caller " + caller
10108 + " (pid=" + Binder.getCallingPid()
10109 + ") when starting service " + service);
10110 }
10111 }
10112
10113 ServiceLookupResult res =
10114 retrieveServiceLocked(service, resolvedType,
10115 callingPid, callingUid);
10116 if (res == null) {
10117 return null;
10118 }
10119 if (res.record == null) {
10120 return new ComponentName("!", res.permission != null
10121 ? res.permission : "private to package");
10122 }
10123 ServiceRecord r = res.record;
Dianne Hackborn39792d22010-08-19 18:01:52 -070010124 int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
10125 callingUid, r.packageName, service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010126 if (unscheduleServiceRestartLocked(r)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010127 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010128 }
10129 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010130 r.callStart = false;
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010131 r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
Dianne Hackborn39792d22010-08-19 18:01:52 -070010132 service, targetPermissionUid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010133 r.lastActivity = SystemClock.uptimeMillis();
10134 synchronized (r.stats.getBatteryStats()) {
10135 r.stats.startRunningLocked();
10136 }
10137 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
10138 return new ComponentName("!", "Service process is bad");
10139 }
10140 return r.name;
10141 }
10142 }
10143
10144 public ComponentName startService(IApplicationThread caller, Intent service,
10145 String resolvedType) {
10146 // Refuse possible leaked file descriptors
10147 if (service != null && service.hasFileDescriptors() == true) {
10148 throw new IllegalArgumentException("File descriptors passed in Intent");
10149 }
10150
10151 synchronized(this) {
10152 final int callingPid = Binder.getCallingPid();
10153 final int callingUid = Binder.getCallingUid();
10154 final long origId = Binder.clearCallingIdentity();
10155 ComponentName res = startServiceLocked(caller, service,
10156 resolvedType, callingPid, callingUid);
10157 Binder.restoreCallingIdentity(origId);
10158 return res;
10159 }
10160 }
10161
10162 ComponentName startServiceInPackage(int uid,
10163 Intent service, String resolvedType) {
10164 synchronized(this) {
10165 final long origId = Binder.clearCallingIdentity();
10166 ComponentName res = startServiceLocked(null, service,
10167 resolvedType, -1, uid);
10168 Binder.restoreCallingIdentity(origId);
10169 return res;
10170 }
10171 }
10172
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010173 private void stopServiceLocked(ServiceRecord service) {
10174 synchronized (service.stats.getBatteryStats()) {
10175 service.stats.stopRunningLocked();
10176 }
10177 service.startRequested = false;
10178 service.callStart = false;
10179 bringDownServiceLocked(service, false);
10180 }
10181
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010182 public int stopService(IApplicationThread caller, Intent service,
10183 String resolvedType) {
10184 // Refuse possible leaked file descriptors
10185 if (service != null && service.hasFileDescriptors() == true) {
10186 throw new IllegalArgumentException("File descriptors passed in Intent");
10187 }
10188
10189 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010190 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010191 + " type=" + resolvedType);
10192
10193 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10194 if (caller != null && callerApp == null) {
10195 throw new SecurityException(
10196 "Unable to find app for caller " + caller
10197 + " (pid=" + Binder.getCallingPid()
10198 + ") when stopping service " + service);
10199 }
10200
10201 // If this service is active, make sure it is stopped.
10202 ServiceLookupResult r = findServiceLocked(service, resolvedType);
10203 if (r != null) {
10204 if (r.record != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010205 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010206 try {
10207 stopServiceLocked(r.record);
10208 } finally {
10209 Binder.restoreCallingIdentity(origId);
10210 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010211 return 1;
10212 }
10213 return -1;
10214 }
10215 }
10216
10217 return 0;
10218 }
10219
10220 public IBinder peekService(Intent service, String resolvedType) {
10221 // Refuse possible leaked file descriptors
10222 if (service != null && service.hasFileDescriptors() == true) {
10223 throw new IllegalArgumentException("File descriptors passed in Intent");
10224 }
10225
10226 IBinder ret = null;
10227
10228 synchronized(this) {
10229 ServiceLookupResult r = findServiceLocked(service, resolvedType);
10230
10231 if (r != null) {
10232 // r.record is null if findServiceLocked() failed the caller permission check
10233 if (r.record == null) {
10234 throw new SecurityException(
10235 "Permission Denial: Accessing service " + r.record.name
10236 + " from pid=" + Binder.getCallingPid()
10237 + ", uid=" + Binder.getCallingUid()
10238 + " requires " + r.permission);
10239 }
10240 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
10241 if (ib != null) {
10242 ret = ib.binder;
10243 }
10244 }
10245 }
10246
10247 return ret;
10248 }
10249
10250 public boolean stopServiceToken(ComponentName className, IBinder token,
10251 int startId) {
10252 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010253 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010254 + " " + token + " startId=" + startId);
10255 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010256 if (r != null) {
10257 if (startId >= 0) {
10258 // Asked to only stop if done with all work. Note that
10259 // to avoid leaks, we will take this as dropping all
10260 // start items up to and including this one.
10261 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
10262 if (si != null) {
10263 while (r.deliveredStarts.size() > 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -070010264 ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
10265 cur.removeUriPermissionsLocked();
10266 if (cur == si) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010267 break;
10268 }
10269 }
10270 }
10271
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010272 if (r.getLastStartId() != startId) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010273 return false;
10274 }
10275
10276 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010277 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010278 + " is last, but have " + r.deliveredStarts.size()
10279 + " remaining args");
10280 }
10281 }
10282
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010283 synchronized (r.stats.getBatteryStats()) {
10284 r.stats.stopRunningLocked();
10285 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010286 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010287 }
10288 final long origId = Binder.clearCallingIdentity();
10289 bringDownServiceLocked(r, false);
10290 Binder.restoreCallingIdentity(origId);
10291 return true;
10292 }
10293 }
10294 return false;
10295 }
10296
10297 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010298 int id, Notification notification, boolean removeNotification) {
10299 final long origId = Binder.clearCallingIdentity();
10300 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010301 synchronized(this) {
10302 ServiceRecord r = findServiceLocked(className, token);
10303 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010304 if (id != 0) {
10305 if (notification == null) {
10306 throw new IllegalArgumentException("null notification");
10307 }
10308 if (r.foregroundId != id) {
10309 r.cancelNotification();
10310 r.foregroundId = id;
10311 }
10312 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
10313 r.foregroundNoti = notification;
10314 r.isForeground = true;
10315 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010316 if (r.app != null) {
10317 updateServiceForegroundLocked(r.app, true);
10318 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010319 } else {
10320 if (r.isForeground) {
10321 r.isForeground = false;
10322 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -070010323 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010324 updateServiceForegroundLocked(r.app, true);
10325 }
10326 }
10327 if (removeNotification) {
10328 r.cancelNotification();
10329 r.foregroundId = 0;
10330 r.foregroundNoti = null;
10331 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010332 }
10333 }
10334 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010335 } finally {
10336 Binder.restoreCallingIdentity(origId);
10337 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010338 }
10339
10340 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
10341 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -070010342 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010343 if (sr.isForeground) {
10344 anyForeground = true;
10345 break;
10346 }
10347 }
10348 if (anyForeground != proc.foregroundServices) {
10349 proc.foregroundServices = anyForeground;
10350 if (oomAdj) {
10351 updateOomAdjLocked();
10352 }
10353 }
10354 }
10355
10356 public int bindService(IApplicationThread caller, IBinder token,
10357 Intent service, String resolvedType,
10358 IServiceConnection connection, int flags) {
10359 // Refuse possible leaked file descriptors
10360 if (service != null && service.hasFileDescriptors() == true) {
10361 throw new IllegalArgumentException("File descriptors passed in Intent");
10362 }
10363
10364 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010365 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010366 + " type=" + resolvedType + " conn=" + connection.asBinder()
10367 + " flags=0x" + Integer.toHexString(flags));
10368 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10369 if (callerApp == null) {
10370 throw new SecurityException(
10371 "Unable to find app for caller " + caller
10372 + " (pid=" + Binder.getCallingPid()
10373 + ") when binding service " + service);
10374 }
10375
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010376 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010377 if (token != null) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -070010378 activity = mMainStack.isInStackLocked(token);
10379 if (activity == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010380 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010381 return 0;
10382 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010383 }
10384
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010385 int clientLabel = 0;
10386 PendingIntent clientIntent = null;
10387
10388 if (callerApp.info.uid == Process.SYSTEM_UID) {
10389 // Hacky kind of thing -- allow system stuff to tell us
10390 // what they are, so we can report this elsewhere for
10391 // others to know why certain services are running.
10392 try {
10393 clientIntent = (PendingIntent)service.getParcelableExtra(
10394 Intent.EXTRA_CLIENT_INTENT);
10395 } catch (RuntimeException e) {
10396 }
10397 if (clientIntent != null) {
10398 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
10399 if (clientLabel != 0) {
10400 // There are no useful extras in the intent, trash them.
10401 // System code calling with this stuff just needs to know
10402 // this will happen.
10403 service = service.cloneFilter();
10404 }
10405 }
10406 }
10407
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010408 ServiceLookupResult res =
10409 retrieveServiceLocked(service, resolvedType,
10410 Binder.getCallingPid(), Binder.getCallingUid());
10411 if (res == null) {
10412 return 0;
10413 }
10414 if (res.record == null) {
10415 return -1;
10416 }
10417 ServiceRecord s = res.record;
10418
10419 final long origId = Binder.clearCallingIdentity();
10420
10421 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010422 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010423 + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010424 }
10425
10426 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
10427 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010428 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010429
10430 IBinder binder = connection.asBinder();
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010431 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
10432 if (clist == null) {
10433 clist = new ArrayList<ConnectionRecord>();
10434 s.connections.put(binder, clist);
10435 }
10436 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010437 b.connections.add(c);
10438 if (activity != null) {
10439 if (activity.connections == null) {
10440 activity.connections = new HashSet<ConnectionRecord>();
10441 }
10442 activity.connections.add(c);
10443 }
10444 b.client.connections.add(c);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010445 clist = mServiceConnections.get(binder);
10446 if (clist == null) {
10447 clist = new ArrayList<ConnectionRecord>();
10448 mServiceConnections.put(binder, clist);
10449 }
10450 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010451
10452 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
10453 s.lastActivity = SystemClock.uptimeMillis();
10454 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
10455 return 0;
10456 }
10457 }
10458
10459 if (s.app != null) {
10460 // This could have made the service more important.
10461 updateOomAdjLocked(s.app);
10462 }
10463
Joe Onorato8a9b2202010-02-26 18:56:32 -080010464 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010465 + ": received=" + b.intent.received
10466 + " apps=" + b.intent.apps.size()
10467 + " doRebind=" + b.intent.doRebind);
10468
10469 if (s.app != null && b.intent.received) {
10470 // Service is already running, so we can immediately
10471 // publish the connection.
10472 try {
10473 c.conn.connected(s.name, b.intent.binder);
10474 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010475 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010476 + " to connection " + c.conn.asBinder()
10477 + " (in " + c.binding.client.processName + ")", e);
10478 }
10479
10480 // If this is the first app connected back to this binding,
10481 // and the service had previously asked to be told when
10482 // rebound, then do so.
10483 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
10484 requestServiceBindingLocked(s, b.intent, true);
10485 }
10486 } else if (!b.intent.requested) {
10487 requestServiceBindingLocked(s, b.intent, false);
10488 }
10489
10490 Binder.restoreCallingIdentity(origId);
10491 }
10492
10493 return 1;
10494 }
10495
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010496 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010497 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010498 IBinder binder = c.conn.asBinder();
10499 AppBindRecord b = c.binding;
10500 ServiceRecord s = b.service;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010501 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
10502 if (clist != null) {
10503 clist.remove(c);
10504 if (clist.size() == 0) {
10505 s.connections.remove(binder);
10506 }
10507 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010508 b.connections.remove(c);
10509 if (c.activity != null && c.activity != skipAct) {
10510 if (c.activity.connections != null) {
10511 c.activity.connections.remove(c);
10512 }
10513 }
10514 if (b.client != skipApp) {
10515 b.client.connections.remove(c);
10516 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010517 clist = mServiceConnections.get(binder);
10518 if (clist != null) {
10519 clist.remove(c);
10520 if (clist.size() == 0) {
10521 mServiceConnections.remove(binder);
10522 }
10523 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010524
10525 if (b.connections.size() == 0) {
10526 b.intent.apps.remove(b.client);
10527 }
10528
Joe Onorato8a9b2202010-02-26 18:56:32 -080010529 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010530 + ": shouldUnbind=" + b.intent.hasBound);
10531 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
10532 && b.intent.hasBound) {
10533 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010534 bumpServiceExecutingLocked(s, "unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010535 updateOomAdjLocked(s.app);
10536 b.intent.hasBound = false;
10537 // Assume the client doesn't want to know about a rebind;
10538 // we will deal with that later if it asks for one.
10539 b.intent.doRebind = false;
10540 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
10541 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010542 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010543 serviceDoneExecutingLocked(s, true);
10544 }
10545 }
10546
10547 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
10548 bringDownServiceLocked(s, false);
10549 }
10550 }
10551
10552 public boolean unbindService(IServiceConnection connection) {
10553 synchronized (this) {
10554 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010555 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010556 ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
10557 if (clist == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010558 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010559 + connection.asBinder());
10560 return false;
10561 }
10562
10563 final long origId = Binder.clearCallingIdentity();
10564
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010565 while (clist.size() > 0) {
10566 ConnectionRecord r = clist.get(0);
10567 removeConnectionLocked(r, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010568
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010569 if (r.binding.service.app != null) {
10570 // This could have made the service less important.
10571 updateOomAdjLocked(r.binding.service.app);
10572 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010573 }
10574
10575 Binder.restoreCallingIdentity(origId);
10576 }
10577
10578 return true;
10579 }
10580
10581 public void publishService(IBinder token, Intent intent, IBinder service) {
10582 // Refuse possible leaked file descriptors
10583 if (intent != null && intent.hasFileDescriptors() == true) {
10584 throw new IllegalArgumentException("File descriptors passed in Intent");
10585 }
10586
10587 synchronized(this) {
10588 if (!(token instanceof ServiceRecord)) {
10589 throw new IllegalArgumentException("Invalid service token");
10590 }
10591 ServiceRecord r = (ServiceRecord)token;
10592
10593 final long origId = Binder.clearCallingIdentity();
10594
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010595 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010596 + " " + intent + ": " + service);
10597 if (r != null) {
10598 Intent.FilterComparison filter
10599 = new Intent.FilterComparison(intent);
10600 IntentBindRecord b = r.bindings.get(filter);
10601 if (b != null && !b.received) {
10602 b.binder = service;
10603 b.requested = true;
10604 b.received = true;
10605 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010606 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010607 = r.connections.values().iterator();
10608 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010609 ArrayList<ConnectionRecord> clist = it.next();
10610 for (int i=0; i<clist.size(); i++) {
10611 ConnectionRecord c = clist.get(i);
10612 if (!filter.equals(c.binding.intent.intent)) {
10613 if (DEBUG_SERVICE) Slog.v(
10614 TAG, "Not publishing to: " + c);
10615 if (DEBUG_SERVICE) Slog.v(
10616 TAG, "Bound intent: " + c.binding.intent.intent);
10617 if (DEBUG_SERVICE) Slog.v(
10618 TAG, "Published intent: " + intent);
10619 continue;
10620 }
10621 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
10622 try {
10623 c.conn.connected(r.name, service);
10624 } catch (Exception e) {
10625 Slog.w(TAG, "Failure sending service " + r.name +
10626 " to connection " + c.conn.asBinder() +
10627 " (in " + c.binding.client.processName + ")", e);
10628 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010629 }
10630 }
10631 }
10632 }
10633
10634 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
10635
10636 Binder.restoreCallingIdentity(origId);
10637 }
10638 }
10639 }
10640
10641 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
10642 // Refuse possible leaked file descriptors
10643 if (intent != null && intent.hasFileDescriptors() == true) {
10644 throw new IllegalArgumentException("File descriptors passed in Intent");
10645 }
10646
10647 synchronized(this) {
10648 if (!(token instanceof ServiceRecord)) {
10649 throw new IllegalArgumentException("Invalid service token");
10650 }
10651 ServiceRecord r = (ServiceRecord)token;
10652
10653 final long origId = Binder.clearCallingIdentity();
10654
10655 if (r != null) {
10656 Intent.FilterComparison filter
10657 = new Intent.FilterComparison(intent);
10658 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010659 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010660 + " at " + b + ": apps="
10661 + (b != null ? b.apps.size() : 0));
10662 if (b != null) {
10663 if (b.apps.size() > 0) {
10664 // Applications have already bound since the last
10665 // unbind, so just rebind right here.
10666 requestServiceBindingLocked(r, b, true);
10667 } else {
10668 // Note to tell the service the next time there is
10669 // a new client.
10670 b.doRebind = true;
10671 }
10672 }
10673
10674 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
10675
10676 Binder.restoreCallingIdentity(origId);
10677 }
10678 }
10679 }
10680
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010681 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010682 synchronized(this) {
10683 if (!(token instanceof ServiceRecord)) {
10684 throw new IllegalArgumentException("Invalid service token");
10685 }
10686 ServiceRecord r = (ServiceRecord)token;
10687 boolean inStopping = mStoppingServices.contains(token);
10688 if (r != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010689 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010690 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010691 + " with incorrect token: given " + token
10692 + ", expected " + r);
10693 return;
10694 }
10695
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010696 if (type == 1) {
10697 // This is a call from a service start... take care of
10698 // book-keeping.
10699 r.callStart = true;
10700 switch (res) {
10701 case Service.START_STICKY_COMPATIBILITY:
10702 case Service.START_STICKY: {
10703 // We are done with the associated start arguments.
10704 r.findDeliveredStart(startId, true);
10705 // Don't stop if killed.
10706 r.stopIfKilled = false;
10707 break;
10708 }
10709 case Service.START_NOT_STICKY: {
10710 // We are done with the associated start arguments.
10711 r.findDeliveredStart(startId, true);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010712 if (r.getLastStartId() == startId) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010713 // There is no more work, and this service
10714 // doesn't want to hang around if killed.
10715 r.stopIfKilled = true;
10716 }
10717 break;
10718 }
10719 case Service.START_REDELIVER_INTENT: {
10720 // We'll keep this item until they explicitly
10721 // call stop for it, but keep track of the fact
10722 // that it was delivered.
10723 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
10724 if (si != null) {
10725 si.deliveryCount = 0;
10726 si.doneExecutingCount++;
10727 // Don't stop if killed.
10728 r.stopIfKilled = true;
10729 }
10730 break;
10731 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010732 case Service.START_TASK_REMOVED_COMPLETE: {
10733 // Special processing for onTaskRemoved(). Don't
10734 // impact normal onStartCommand() processing.
10735 r.findDeliveredStart(startId, true);
10736 break;
10737 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010738 default:
10739 throw new IllegalArgumentException(
10740 "Unknown service start result: " + res);
10741 }
10742 if (res == Service.START_STICKY_COMPATIBILITY) {
10743 r.callStart = false;
10744 }
10745 }
10746
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010747 final long origId = Binder.clearCallingIdentity();
10748 serviceDoneExecutingLocked(r, inStopping);
10749 Binder.restoreCallingIdentity(origId);
10750 } else {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010751 Slog.w(TAG, "Done executing unknown service from pid "
10752 + Binder.getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010753 }
10754 }
10755 }
10756
10757 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010758 if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
10759 + ": nesting=" + r.executeNesting
10760 + ", inStopping=" + inStopping + ", app=" + r.app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070010761 else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010762 r.executeNesting--;
10763 if (r.executeNesting <= 0 && r.app != null) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010764 if (DEBUG_SERVICE) Slog.v(TAG,
10765 "Nesting at 0 of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010766 r.app.executingServices.remove(r);
10767 if (r.app.executingServices.size() == 0) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010768 if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,
10769 "No more executingServices of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010770 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
10771 }
10772 if (inStopping) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010773 if (DEBUG_SERVICE) Slog.v(TAG,
10774 "doneExecuting remove stopping " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010775 mStoppingServices.remove(r);
Mattias Petersson3996b412010-10-27 09:32:51 +020010776 r.bindings.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010777 }
10778 updateOomAdjLocked(r.app);
10779 }
10780 }
10781
10782 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010783 String anrMessage = null;
10784
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010785 synchronized(this) {
10786 if (proc.executingServices.size() == 0 || proc.thread == null) {
10787 return;
10788 }
10789 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
10790 Iterator<ServiceRecord> it = proc.executingServices.iterator();
10791 ServiceRecord timeout = null;
10792 long nextTime = 0;
10793 while (it.hasNext()) {
10794 ServiceRecord sr = it.next();
10795 if (sr.executingStart < maxTime) {
10796 timeout = sr;
10797 break;
10798 }
10799 if (sr.executingStart > nextTime) {
10800 nextTime = sr.executingStart;
10801 }
10802 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010803 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010804 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010805 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010806 } else {
10807 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
10808 msg.obj = proc;
10809 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
10810 }
10811 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010812
10813 if (anrMessage != null) {
10814 appNotResponding(proc, null, null, anrMessage);
10815 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010816 }
10817
10818 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070010819 // BACKUP AND RESTORE
10820 // =========================================================
10821
10822 // Cause the target app to be launched if necessary and its backup agent
10823 // instantiated. The backup agent will invoke backupAgentCreated() on the
10824 // activity manager to announce its creation.
10825 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010826 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070010827 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
10828
10829 synchronized(this) {
10830 // !!! TODO: currently no check here that we're already bound
10831 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
10832 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
10833 synchronized (stats) {
10834 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
10835 }
10836
Dianne Hackborne7f97212011-02-24 14:40:20 -080010837 // Backup agent is now in use, its package can't be stopped.
10838 try {
10839 AppGlobals.getPackageManager().setPackageStoppedState(
10840 app.packageName, false);
10841 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -080010842 } catch (IllegalArgumentException e) {
10843 Slog.w(TAG, "Failed trying to unstop package "
10844 + app.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -080010845 }
10846
Christopher Tate181fafa2009-05-14 11:12:14 -070010847 BackupRecord r = new BackupRecord(ss, app, backupMode);
Christopher Tate4a627c72011-04-01 14:43:32 -070010848 ComponentName hostingName = (backupMode == IApplicationThread.BACKUP_MODE_INCREMENTAL)
10849 ? new ComponentName(app.packageName, app.backupAgentName)
10850 : new ComponentName("android", "FullBackupAgent");
Christopher Tate181fafa2009-05-14 11:12:14 -070010851 // startProcessLocked() returns existing proc's record if it's already running
10852 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010853 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070010854 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010855 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070010856 return false;
10857 }
10858
10859 r.app = proc;
10860 mBackupTarget = r;
10861 mBackupAppName = app.packageName;
10862
Christopher Tate6fa95972009-06-05 18:43:55 -070010863 // Try not to kill the process during backup
10864 updateOomAdjLocked(proc);
10865
Christopher Tate181fafa2009-05-14 11:12:14 -070010866 // If the process is already attached, schedule the creation of the backup agent now.
10867 // If it is not yet live, this will be done when it attaches to the framework.
10868 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010869 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070010870 try {
Dianne Hackborne2515ee2011-04-27 18:52:56 -040010871 proc.thread.scheduleCreateBackupAgent(app,
10872 compatibilityInfoForPackageLocked(app), backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070010873 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070010874 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070010875 }
10876 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010877 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070010878 }
10879 // Invariants: at this point, the target app process exists and the application
10880 // is either already running or in the process of coming up. mBackupTarget and
10881 // mBackupAppName describe the app, so that when it binds back to the AM we
10882 // know that it's scheduled for a backup-agent operation.
10883 }
10884
10885 return true;
10886 }
10887
10888 // A backup agent has just come up
10889 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010890 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070010891 + " = " + agent);
10892
10893 synchronized(this) {
10894 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010895 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070010896 return;
10897 }
Dianne Hackborn06740692010-09-22 22:46:21 -070010898 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010899
Dianne Hackborn06740692010-09-22 22:46:21 -070010900 long oldIdent = Binder.clearCallingIdentity();
10901 try {
10902 IBackupManager bm = IBackupManager.Stub.asInterface(
10903 ServiceManager.getService(Context.BACKUP_SERVICE));
10904 bm.agentConnected(agentPackageName, agent);
10905 } catch (RemoteException e) {
10906 // can't happen; the backup manager service is local
10907 } catch (Exception e) {
10908 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
10909 e.printStackTrace();
10910 } finally {
10911 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070010912 }
10913 }
10914
10915 // done with this agent
10916 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010917 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070010918 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010919 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070010920 return;
10921 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010922
10923 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070010924 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010925 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070010926 return;
10927 }
10928
Christopher Tate181fafa2009-05-14 11:12:14 -070010929 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010930 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070010931 return;
10932 }
10933
Christopher Tate6fa95972009-06-05 18:43:55 -070010934 ProcessRecord proc = mBackupTarget.app;
10935 mBackupTarget = null;
10936 mBackupAppName = null;
10937
10938 // Not backing this app up any more; reset its OOM adjustment
10939 updateOomAdjLocked(proc);
10940
Christopher Tatec7b31e32009-06-10 15:49:30 -070010941 // If the app crashed during backup, 'thread' will be null here
10942 if (proc.thread != null) {
10943 try {
Dianne Hackborne2515ee2011-04-27 18:52:56 -040010944 proc.thread.scheduleDestroyBackupAgent(appInfo,
10945 compatibilityInfoForPackageLocked(appInfo));
Christopher Tatec7b31e32009-06-10 15:49:30 -070010946 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010947 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070010948 e.printStackTrace();
10949 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010950 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010951 }
10952 }
10953 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010954 // BROADCASTS
10955 // =========================================================
10956
Josh Bartel7f208742010-02-25 11:01:44 -060010957 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010958 List cur) {
10959 final ContentResolver resolver = mContext.getContentResolver();
10960 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
10961 if (list == null) {
10962 return cur;
10963 }
10964 int N = list.size();
10965 for (int i=0; i<N; i++) {
10966 Intent intent = list.get(i);
10967 if (filter.match(resolver, intent, true, TAG) >= 0) {
10968 if (cur == null) {
10969 cur = new ArrayList<Intent>();
10970 }
10971 cur.add(intent);
10972 }
10973 }
10974 return cur;
10975 }
10976
10977 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010978 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010979 + mBroadcastsScheduled);
10980
10981 if (mBroadcastsScheduled) {
10982 return;
10983 }
10984 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
10985 mBroadcastsScheduled = true;
10986 }
10987
Dianne Hackborn6c418d52011-06-29 14:05:33 -070010988 public Intent registerReceiver(IApplicationThread caller, String callerPackage,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010989 IIntentReceiver receiver, IntentFilter filter, String permission) {
10990 synchronized(this) {
10991 ProcessRecord callerApp = null;
10992 if (caller != null) {
10993 callerApp = getRecordForAppLocked(caller);
10994 if (callerApp == null) {
10995 throw new SecurityException(
10996 "Unable to find app for caller " + caller
10997 + " (pid=" + Binder.getCallingPid()
10998 + ") when registering receiver " + receiver);
10999 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -070011000 if (callerApp.info.uid != Process.SYSTEM_UID &&
11001 !callerApp.pkgList.contains(callerPackage)) {
11002 throw new SecurityException("Given caller package " + callerPackage
11003 + " is not running in process " + callerApp);
11004 }
11005 } else {
11006 callerPackage = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011007 }
11008
11009 List allSticky = null;
11010
11011 // Look for any matching sticky broadcasts...
11012 Iterator actions = filter.actionsIterator();
11013 if (actions != null) {
11014 while (actions.hasNext()) {
11015 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -060011016 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011017 }
11018 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060011019 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011020 }
11021
11022 // The first sticky in the list is returned directly back to
11023 // the client.
11024 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
11025
Joe Onorato8a9b2202010-02-26 18:56:32 -080011026 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011027 + ": " + sticky);
11028
11029 if (receiver == null) {
11030 return sticky;
11031 }
11032
11033 ReceiverList rl
11034 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
11035 if (rl == null) {
11036 rl = new ReceiverList(this, callerApp,
11037 Binder.getCallingPid(),
11038 Binder.getCallingUid(), receiver);
11039 if (rl.app != null) {
11040 rl.app.receivers.add(rl);
11041 } else {
11042 try {
11043 receiver.asBinder().linkToDeath(rl, 0);
11044 } catch (RemoteException e) {
11045 return sticky;
11046 }
11047 rl.linkedToDeath = true;
11048 }
11049 mRegisteredReceivers.put(receiver.asBinder(), rl);
11050 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -070011051 BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage, permission);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011052 rl.add(bf);
11053 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011054 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011055 }
11056 mReceiverResolver.addFilter(bf);
11057
11058 // Enqueue broadcasts for all existing stickies that match
11059 // this filter.
11060 if (allSticky != null) {
11061 ArrayList receivers = new ArrayList();
11062 receivers.add(bf);
11063
11064 int N = allSticky.size();
11065 for (int i=0; i<N; i++) {
11066 Intent intent = (Intent)allSticky.get(i);
11067 BroadcastRecord r = new BroadcastRecord(intent, null,
11068 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011069 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011070 if (mParallelBroadcasts.size() == 0) {
11071 scheduleBroadcastsLocked();
11072 }
11073 mParallelBroadcasts.add(r);
11074 }
11075 }
11076
11077 return sticky;
11078 }
11079 }
11080
11081 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011082 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011083
11084 boolean doNext = false;
11085
11086 synchronized(this) {
11087 ReceiverList rl
11088 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
11089 if (rl != null) {
11090 if (rl.curBroadcast != null) {
11091 BroadcastRecord r = rl.curBroadcast;
11092 doNext = finishReceiverLocked(
11093 receiver.asBinder(), r.resultCode, r.resultData,
11094 r.resultExtras, r.resultAbort, true);
11095 }
11096
11097 if (rl.app != null) {
11098 rl.app.receivers.remove(rl);
11099 }
11100 removeReceiverLocked(rl);
11101 if (rl.linkedToDeath) {
11102 rl.linkedToDeath = false;
11103 rl.receiver.asBinder().unlinkToDeath(rl, 0);
11104 }
11105 }
11106 }
11107
11108 if (!doNext) {
11109 return;
11110 }
11111
11112 final long origId = Binder.clearCallingIdentity();
11113 processNextBroadcast(false);
11114 trimApplications();
11115 Binder.restoreCallingIdentity(origId);
11116 }
11117
11118 void removeReceiverLocked(ReceiverList rl) {
11119 mRegisteredReceivers.remove(rl.receiver.asBinder());
11120 int N = rl.size();
11121 for (int i=0; i<N; i++) {
11122 mReceiverResolver.removeFilter(rl.get(i));
11123 }
11124 }
11125
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070011126 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
11127 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
11128 ProcessRecord r = mLruProcesses.get(i);
11129 if (r.thread != null) {
11130 try {
11131 r.thread.dispatchPackageBroadcast(cmd, packages);
11132 } catch (RemoteException ex) {
11133 }
11134 }
11135 }
11136 }
11137
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011138 private final int broadcastIntentLocked(ProcessRecord callerApp,
11139 String callerPackage, Intent intent, String resolvedType,
11140 IIntentReceiver resultTo, int resultCode, String resultData,
11141 Bundle map, String requiredPermission,
11142 boolean ordered, boolean sticky, int callingPid, int callingUid) {
11143 intent = new Intent(intent);
11144
Dianne Hackborne7f97212011-02-24 14:40:20 -080011145 // By default broadcasts do not go to stopped apps.
11146 intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
11147
Joe Onorato8a9b2202010-02-26 18:56:32 -080011148 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011149 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
11150 + " ordered=" + ordered);
11151 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011152 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011153 }
11154
11155 // Handle special intents: if this broadcast is from the package
11156 // manager about a package being removed, we need to remove all of
11157 // its activities from the history stack.
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011158 final boolean uidRemoved = Intent.ACTION_UID_REMOVED.equals(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011159 intent.getAction());
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011160 if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
11161 || Intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080011162 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011163 || uidRemoved) {
11164 if (checkComponentPermission(
11165 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011166 callingPid, callingUid, -1, true)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011167 == PackageManager.PERMISSION_GRANTED) {
11168 if (uidRemoved) {
11169 final Bundle intentExtras = intent.getExtras();
11170 final int uid = intentExtras != null
11171 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
11172 if (uid >= 0) {
11173 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
11174 synchronized (bs) {
11175 bs.removeUidStatsLocked(uid);
11176 }
11177 }
11178 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011179 // If resources are unvailble just force stop all
11180 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080011181 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011182 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
11183 if (list != null && (list.length > 0)) {
11184 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011185 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011186 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070011187 sendPackageBroadcastLocked(
11188 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011189 }
11190 } else {
11191 Uri data = intent.getData();
11192 String ssp;
11193 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
11194 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
11195 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011196 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070011197 }
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011198 if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070011199 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
11200 new String[] {ssp});
11201 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011202 }
11203 }
11204 }
11205 } else {
11206 String msg = "Permission Denial: " + intent.getAction()
11207 + " broadcast from " + callerPackage + " (pid=" + callingPid
11208 + ", uid=" + callingUid + ")"
11209 + " requires "
11210 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011211 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011212 throw new SecurityException(msg);
11213 }
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011214
11215 // Special case for adding a package: by default turn on compatibility
11216 // mode.
11217 } else if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())) {
Dianne Hackborn8ea5e1d2011-05-27 16:45:31 -070011218 Uri data = intent.getData();
11219 String ssp;
11220 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
11221 mCompatModePackages.handlePackageAddedLocked(ssp,
11222 intent.getBooleanExtra(Intent.EXTRA_REPLACING, false));
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011223 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011224 }
11225
11226 /*
11227 * If this is the time zone changed action, queue up a message that will reset the timezone
11228 * of all currently running processes. This message will get queued up before the broadcast
11229 * happens.
11230 */
11231 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
11232 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
11233 }
11234
Robert Greenwalt03595d02010-11-02 14:08:23 -070011235 if (intent.ACTION_CLEAR_DNS_CACHE.equals(intent.getAction())) {
11236 mHandler.sendEmptyMessage(CLEAR_DNS_CACHE);
11237 }
11238
Robert Greenwalt434203a2010-10-11 16:00:27 -070011239 if (Proxy.PROXY_CHANGE_ACTION.equals(intent.getAction())) {
11240 ProxyProperties proxy = intent.getParcelableExtra("proxy");
11241 mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY, proxy));
11242 }
11243
Dianne Hackborn854060af2009-07-09 18:14:31 -070011244 /*
11245 * Prevent non-system code (defined here to be non-persistent
11246 * processes) from sending protected broadcasts.
11247 */
11248 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
11249 || callingUid == Process.SHELL_UID || callingUid == 0) {
11250 // Always okay.
11251 } else if (callerApp == null || !callerApp.persistent) {
11252 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011253 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -070011254 intent.getAction())) {
11255 String msg = "Permission Denial: not allowed to send broadcast "
11256 + intent.getAction() + " from pid="
11257 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011258 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070011259 throw new SecurityException(msg);
11260 }
11261 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011262 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070011263 return BROADCAST_SUCCESS;
11264 }
11265 }
11266
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011267 // Add to the sticky list if requested.
11268 if (sticky) {
11269 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
11270 callingPid, callingUid)
11271 != PackageManager.PERMISSION_GRANTED) {
11272 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
11273 + callingPid + ", uid=" + callingUid
11274 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011275 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011276 throw new SecurityException(msg);
11277 }
11278 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011279 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011280 + " and enforce permission " + requiredPermission);
11281 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
11282 }
11283 if (intent.getComponent() != null) {
11284 throw new SecurityException(
11285 "Sticky broadcasts can't target a specific component");
11286 }
11287 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
11288 if (list == null) {
11289 list = new ArrayList<Intent>();
11290 mStickyBroadcasts.put(intent.getAction(), list);
11291 }
11292 int N = list.size();
11293 int i;
11294 for (i=0; i<N; i++) {
11295 if (intent.filterEquals(list.get(i))) {
11296 // This sticky already exists, replace it.
11297 list.set(i, new Intent(intent));
11298 break;
11299 }
11300 }
11301 if (i >= N) {
11302 list.add(new Intent(intent));
11303 }
11304 }
11305
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011306 // Figure out who all will receive this broadcast.
11307 List receivers = null;
11308 List<BroadcastFilter> registeredReceivers = null;
11309 try {
11310 if (intent.getComponent() != null) {
11311 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011312 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070011313 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011314 if (ai != null) {
11315 receivers = new ArrayList();
11316 ResolveInfo ri = new ResolveInfo();
11317 ri.activityInfo = ai;
11318 receivers.add(ri);
11319 }
11320 } else {
11321 // Need to resolve the intent to interested receivers...
11322 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
11323 == 0) {
11324 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011325 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011326 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011327 }
Mihai Preda074edef2009-05-18 17:13:31 +020011328 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011329 }
11330 } catch (RemoteException ex) {
11331 // pm is in same process, this will never happen.
11332 }
11333
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011334 final boolean replacePending =
11335 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
11336
Joe Onorato8a9b2202010-02-26 18:56:32 -080011337 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011338 + " replacePending=" + replacePending);
11339
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011340 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
11341 if (!ordered && NR > 0) {
11342 // If we are not serializing this broadcast, then send the
11343 // registered receivers separately so they don't wait for the
11344 // components to be launched.
11345 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
11346 callerPackage, callingPid, callingUid, requiredPermission,
11347 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011348 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011349 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011350 TAG, "Enqueueing parallel broadcast " + r
11351 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011352 boolean replaced = false;
11353 if (replacePending) {
11354 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
11355 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011356 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011357 "***** DROPPING PARALLEL: " + intent);
11358 mParallelBroadcasts.set(i, r);
11359 replaced = true;
11360 break;
11361 }
11362 }
11363 }
11364 if (!replaced) {
11365 mParallelBroadcasts.add(r);
11366 scheduleBroadcastsLocked();
11367 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011368 registeredReceivers = null;
11369 NR = 0;
11370 }
11371
11372 // Merge into one list.
11373 int ir = 0;
11374 if (receivers != null) {
11375 // A special case for PACKAGE_ADDED: do not allow the package
11376 // being added to see this broadcast. This prevents them from
11377 // using this as a back door to get run as soon as they are
11378 // installed. Maybe in the future we want to have a special install
11379 // broadcast or such for apps, but we'd like to deliberately make
11380 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011381 String skipPackages[] = null;
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011382 if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
11383 || Intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
11384 || Intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011385 Uri data = intent.getData();
11386 if (data != null) {
11387 String pkgName = data.getSchemeSpecificPart();
11388 if (pkgName != null) {
11389 skipPackages = new String[] { pkgName };
11390 }
11391 }
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011392 } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011393 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070011394 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011395 if (skipPackages != null && (skipPackages.length > 0)) {
11396 for (String skipPackage : skipPackages) {
11397 if (skipPackage != null) {
11398 int NT = receivers.size();
11399 for (int it=0; it<NT; it++) {
11400 ResolveInfo curt = (ResolveInfo)receivers.get(it);
11401 if (curt.activityInfo.packageName.equals(skipPackage)) {
11402 receivers.remove(it);
11403 it--;
11404 NT--;
11405 }
11406 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011407 }
11408 }
11409 }
11410
11411 int NT = receivers != null ? receivers.size() : 0;
11412 int it = 0;
11413 ResolveInfo curt = null;
11414 BroadcastFilter curr = null;
11415 while (it < NT && ir < NR) {
11416 if (curt == null) {
11417 curt = (ResolveInfo)receivers.get(it);
11418 }
11419 if (curr == null) {
11420 curr = registeredReceivers.get(ir);
11421 }
11422 if (curr.getPriority() >= curt.priority) {
11423 // Insert this broadcast record into the final list.
11424 receivers.add(it, curr);
11425 ir++;
11426 curr = null;
11427 it++;
11428 NT++;
11429 } else {
11430 // Skip to the next ResolveInfo in the final list.
11431 it++;
11432 curt = null;
11433 }
11434 }
11435 }
11436 while (ir < NR) {
11437 if (receivers == null) {
11438 receivers = new ArrayList();
11439 }
11440 receivers.add(registeredReceivers.get(ir));
11441 ir++;
11442 }
11443
11444 if ((receivers != null && receivers.size() > 0)
11445 || resultTo != null) {
11446 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
11447 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011448 receivers, resultTo, resultCode, resultData, map, ordered,
11449 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011450 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011451 TAG, "Enqueueing ordered broadcast " + r
11452 + ": prev had " + mOrderedBroadcasts.size());
11453 if (DEBUG_BROADCAST) {
11454 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011455 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011456 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011457 boolean replaced = false;
11458 if (replacePending) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011459 for (int i=mOrderedBroadcasts.size()-1; i>0; i--) {
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011460 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011461 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011462 "***** DROPPING ORDERED: " + intent);
11463 mOrderedBroadcasts.set(i, r);
11464 replaced = true;
11465 break;
11466 }
11467 }
11468 }
11469 if (!replaced) {
11470 mOrderedBroadcasts.add(r);
11471 scheduleBroadcastsLocked();
11472 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011473 }
11474
11475 return BROADCAST_SUCCESS;
11476 }
11477
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011478 final Intent verifyBroadcastLocked(Intent intent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011479 // Refuse possible leaked file descriptors
11480 if (intent != null && intent.hasFileDescriptors() == true) {
11481 throw new IllegalArgumentException("File descriptors passed in Intent");
11482 }
11483
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011484 int flags = intent.getFlags();
11485
11486 if (!mProcessesReady) {
11487 // if the caller really truly claims to know what they're doing, go
11488 // ahead and allow the broadcast without launching any receivers
11489 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
11490 intent = new Intent(intent);
11491 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
11492 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
11493 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
11494 + " before boot completion");
11495 throw new IllegalStateException("Cannot broadcast before boot completed");
11496 }
11497 }
11498
11499 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
11500 throw new IllegalArgumentException(
11501 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
11502 }
11503
11504 return intent;
11505 }
11506
11507 public final int broadcastIntent(IApplicationThread caller,
11508 Intent intent, String resolvedType, IIntentReceiver resultTo,
11509 int resultCode, String resultData, Bundle map,
11510 String requiredPermission, boolean serialized, boolean sticky) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011511 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011512 intent = verifyBroadcastLocked(intent);
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011513
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011514 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11515 final int callingPid = Binder.getCallingPid();
11516 final int callingUid = Binder.getCallingUid();
11517 final long origId = Binder.clearCallingIdentity();
11518 int res = broadcastIntentLocked(callerApp,
11519 callerApp != null ? callerApp.info.packageName : null,
11520 intent, resolvedType, resultTo,
11521 resultCode, resultData, map, requiredPermission, serialized,
11522 sticky, callingPid, callingUid);
11523 Binder.restoreCallingIdentity(origId);
11524 return res;
11525 }
11526 }
11527
11528 int broadcastIntentInPackage(String packageName, int uid,
11529 Intent intent, String resolvedType, IIntentReceiver resultTo,
11530 int resultCode, String resultData, Bundle map,
11531 String requiredPermission, boolean serialized, boolean sticky) {
11532 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011533 intent = verifyBroadcastLocked(intent);
11534
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011535 final long origId = Binder.clearCallingIdentity();
11536 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
11537 resultTo, resultCode, resultData, map, requiredPermission,
11538 serialized, sticky, -1, uid);
11539 Binder.restoreCallingIdentity(origId);
11540 return res;
11541 }
11542 }
11543
11544 public final void unbroadcastIntent(IApplicationThread caller,
11545 Intent intent) {
11546 // Refuse possible leaked file descriptors
11547 if (intent != null && intent.hasFileDescriptors() == true) {
11548 throw new IllegalArgumentException("File descriptors passed in Intent");
11549 }
11550
11551 synchronized(this) {
11552 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
11553 != PackageManager.PERMISSION_GRANTED) {
11554 String msg = "Permission Denial: unbroadcastIntent() from pid="
11555 + Binder.getCallingPid()
11556 + ", uid=" + Binder.getCallingUid()
11557 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011558 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011559 throw new SecurityException(msg);
11560 }
11561 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
11562 if (list != null) {
11563 int N = list.size();
11564 int i;
11565 for (i=0; i<N; i++) {
11566 if (intent.filterEquals(list.get(i))) {
11567 list.remove(i);
11568 break;
11569 }
11570 }
11571 }
11572 }
11573 }
11574
11575 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
11576 String resultData, Bundle resultExtras, boolean resultAbort,
11577 boolean explicit) {
11578 if (mOrderedBroadcasts.size() == 0) {
11579 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011580 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011581 }
11582 return false;
11583 }
11584 BroadcastRecord r = mOrderedBroadcasts.get(0);
11585 if (r.receiver == null) {
11586 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011587 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011588 }
11589 return false;
11590 }
11591 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011592 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011593 return false;
11594 }
11595 int state = r.state;
Dianne Hackbornce86ba82011-07-13 19:33:41 -070011596 r.state = BroadcastRecord.IDLE;
11597 if (state == BroadcastRecord.IDLE) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011598 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011599 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011600 }
11601 }
11602 r.receiver = null;
11603 r.intent.setComponent(null);
11604 if (r.curApp != null) {
11605 r.curApp.curReceiver = null;
11606 }
11607 if (r.curFilter != null) {
11608 r.curFilter.receiverList.curBroadcast = null;
11609 }
11610 r.curFilter = null;
11611 r.curApp = null;
11612 r.curComponent = null;
11613 r.curReceiver = null;
11614 mPendingBroadcast = null;
11615
11616 r.resultCode = resultCode;
11617 r.resultData = resultData;
11618 r.resultExtras = resultExtras;
11619 r.resultAbort = resultAbort;
11620
11621 // We will process the next receiver right now if this is finishing
11622 // an app receiver (which is always asynchronous) or after we have
11623 // come back from calling a receiver.
11624 return state == BroadcastRecord.APP_RECEIVE
11625 || state == BroadcastRecord.CALL_DONE_RECEIVE;
11626 }
11627
11628 public void finishReceiver(IBinder who, int resultCode, String resultData,
11629 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011630 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011631
11632 // Refuse possible leaked file descriptors
11633 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
11634 throw new IllegalArgumentException("File descriptors passed in Bundle");
11635 }
11636
11637 boolean doNext;
11638
11639 final long origId = Binder.clearCallingIdentity();
11640
11641 synchronized(this) {
11642 doNext = finishReceiverLocked(
11643 who, resultCode, resultData, resultExtras, resultAbort, true);
11644 }
11645
11646 if (doNext) {
11647 processNextBroadcast(false);
11648 }
11649 trimApplications();
11650
11651 Binder.restoreCallingIdentity(origId);
11652 }
11653
Jeff Brown4d94a762010-09-23 11:33:28 -070011654 private final void logBroadcastReceiverDiscardLocked(BroadcastRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011655 if (r.nextReceiver > 0) {
11656 Object curReceiver = r.receivers.get(r.nextReceiver-1);
11657 if (curReceiver instanceof BroadcastFilter) {
11658 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080011659 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011660 System.identityHashCode(r),
11661 r.intent.getAction(),
11662 r.nextReceiver - 1,
11663 System.identityHashCode(bf));
11664 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080011665 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011666 System.identityHashCode(r),
11667 r.intent.getAction(),
11668 r.nextReceiver - 1,
11669 ((ResolveInfo)curReceiver).toString());
11670 }
11671 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011672 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011673 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011674 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011675 System.identityHashCode(r),
11676 r.intent.getAction(),
11677 r.nextReceiver,
11678 "NONE");
11679 }
11680 }
11681
Jeff Brown4d94a762010-09-23 11:33:28 -070011682 private final void setBroadcastTimeoutLocked(long timeoutTime) {
11683 if (! mPendingBroadcastTimeoutMessage) {
11684 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
11685 mHandler.sendMessageAtTime(msg, timeoutTime);
11686 mPendingBroadcastTimeoutMessage = true;
11687 }
11688 }
11689
11690 private final void cancelBroadcastTimeoutLocked() {
11691 if (mPendingBroadcastTimeoutMessage) {
11692 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
11693 mPendingBroadcastTimeoutMessage = false;
11694 }
11695 }
11696
11697 private final void broadcastTimeoutLocked(boolean fromMsg) {
11698 if (fromMsg) {
11699 mPendingBroadcastTimeoutMessage = false;
11700 }
11701
11702 if (mOrderedBroadcasts.size() == 0) {
11703 return;
11704 }
11705
11706 long now = SystemClock.uptimeMillis();
11707 BroadcastRecord r = mOrderedBroadcasts.get(0);
11708 if (fromMsg) {
11709 if (mDidDexOpt) {
11710 // Delay timeouts until dexopt finishes.
11711 mDidDexOpt = false;
11712 long timeoutTime = SystemClock.uptimeMillis() + BROADCAST_TIMEOUT;
11713 setBroadcastTimeoutLocked(timeoutTime);
11714 return;
11715 }
11716 if (! mProcessesReady) {
11717 // Only process broadcast timeouts if the system is ready. That way
11718 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
11719 // to do heavy lifting for system up.
11720 return;
11721 }
11722
11723 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
11724 if (timeoutTime > now) {
11725 // We can observe premature timeouts because we do not cancel and reset the
11726 // broadcast timeout message after each receiver finishes. Instead, we set up
11727 // an initial timeout then kick it down the road a little further as needed
11728 // when it expires.
11729 if (DEBUG_BROADCAST) Slog.v(TAG,
11730 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
11731 + timeoutTime);
11732 setBroadcastTimeoutLocked(timeoutTime);
11733 return;
11734 }
11735 }
11736
11737 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver
11738 + ", started " + (now - r.receiverTime) + "ms ago");
11739 r.receiverTime = now;
11740 r.anrCount++;
11741
11742 // Current receiver has passed its expiration date.
11743 if (r.nextReceiver <= 0) {
11744 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
11745 return;
11746 }
11747
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011748 ProcessRecord app = null;
11749 String anrMessage = null;
11750
Jeff Brown4d94a762010-09-23 11:33:28 -070011751 Object curReceiver = r.receivers.get(r.nextReceiver-1);
11752 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
11753 logBroadcastReceiverDiscardLocked(r);
11754 if (curReceiver instanceof BroadcastFilter) {
11755 BroadcastFilter bf = (BroadcastFilter)curReceiver;
11756 if (bf.receiverList.pid != 0
11757 && bf.receiverList.pid != MY_PID) {
11758 synchronized (this.mPidsSelfLocked) {
11759 app = this.mPidsSelfLocked.get(
11760 bf.receiverList.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011761 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011762 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011763 } else {
11764 app = r.curApp;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011765 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011766
Jeff Brown4d94a762010-09-23 11:33:28 -070011767 if (app != null) {
11768 anrMessage = "Broadcast of " + r.intent.toString();
11769 }
11770
11771 if (mPendingBroadcast == r) {
11772 mPendingBroadcast = null;
11773 }
11774
11775 // Move on to the next receiver.
11776 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
11777 r.resultExtras, r.resultAbort, true);
11778 scheduleBroadcastsLocked();
11779
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011780 if (anrMessage != null) {
Jeff Brown4d94a762010-09-23 11:33:28 -070011781 // Post the ANR to the handler since we do not want to process ANRs while
11782 // potentially holding our lock.
11783 mHandler.post(new AppNotResponding(app, anrMessage));
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011784 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011785 }
11786
11787 private final void processCurBroadcastLocked(BroadcastRecord r,
11788 ProcessRecord app) throws RemoteException {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011789 if (DEBUG_BROADCAST) Slog.v(TAG,
11790 "Process cur broadcast " + r + " for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011791 if (app.thread == null) {
11792 throw new RemoteException();
11793 }
11794 r.receiver = app.thread.asBinder();
11795 r.curApp = app;
11796 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011797 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011798
11799 // Tell the application to launch this receiver.
11800 r.intent.setComponent(r.curComponent);
11801
11802 boolean started = false;
11803 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011804 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011805 "Delivering to component " + r.curComponent
11806 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070011807 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011808 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
Dianne Hackborne2515ee2011-04-27 18:52:56 -040011809 compatibilityInfoForPackageLocked(r.curReceiver.applicationInfo),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011810 r.resultCode, r.resultData, r.resultExtras, r.ordered);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011811 if (DEBUG_BROADCAST) Slog.v(TAG,
11812 "Process cur broadcast " + r + " DELIVERED for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011813 started = true;
11814 } finally {
11815 if (!started) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011816 if (DEBUG_BROADCAST) Slog.v(TAG,
11817 "Process cur broadcast " + r + ": NOT STARTED!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011818 r.receiver = null;
11819 r.curApp = null;
11820 app.curReceiver = null;
11821 }
11822 }
11823
11824 }
11825
Jeff Brown4d94a762010-09-23 11:33:28 -070011826 static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011827 Intent intent, int resultCode, String data, Bundle extras,
11828 boolean ordered, boolean sticky) throws RemoteException {
Jeff Brown4d94a762010-09-23 11:33:28 -070011829 // Send the intent to the receiver asynchronously using one-way binder calls.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011830 if (app != null && app.thread != null) {
11831 // If we have an app thread, do the call through that so it is
11832 // correctly ordered with other one-way calls.
11833 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011834 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011835 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011836 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011837 }
11838 }
11839
Jeff Brown4d94a762010-09-23 11:33:28 -070011840 private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011841 BroadcastFilter filter, boolean ordered) {
11842 boolean skip = false;
11843 if (filter.requiredPermission != null) {
11844 int perm = checkComponentPermission(filter.requiredPermission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011845 r.callingPid, r.callingUid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011846 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011847 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011848 + r.intent.toString()
11849 + " from " + r.callerPackage + " (pid="
11850 + r.callingPid + ", uid=" + r.callingUid + ")"
11851 + " requires " + filter.requiredPermission
11852 + " due to registered receiver " + filter);
11853 skip = true;
11854 }
11855 }
11856 if (r.requiredPermission != null) {
11857 int perm = checkComponentPermission(r.requiredPermission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011858 filter.receiverList.pid, filter.receiverList.uid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011859 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011860 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011861 + r.intent.toString()
11862 + " to " + filter.receiverList.app
11863 + " (pid=" + filter.receiverList.pid
11864 + ", uid=" + filter.receiverList.uid + ")"
11865 + " requires " + r.requiredPermission
11866 + " due to sender " + r.callerPackage
11867 + " (uid " + r.callingUid + ")");
11868 skip = true;
11869 }
11870 }
11871
11872 if (!skip) {
11873 // If this is not being sent as an ordered broadcast, then we
11874 // don't want to touch the fields that keep track of the current
11875 // state of ordered broadcasts.
11876 if (ordered) {
11877 r.receiver = filter.receiverList.receiver.asBinder();
11878 r.curFilter = filter;
11879 filter.receiverList.curBroadcast = r;
11880 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011881 if (filter.receiverList.app != null) {
11882 // Bump hosting application to no longer be in background
11883 // scheduling class. Note that we can't do that if there
11884 // isn't an app... but we can only be in that case for
11885 // things that directly call the IActivityManager API, which
11886 // are already core system stuff so don't matter for this.
11887 r.curApp = filter.receiverList.app;
11888 filter.receiverList.app.curReceiver = r;
11889 updateOomAdjLocked();
11890 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011891 }
11892 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011893 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011894 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011895 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011896 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011897 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011898 performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011899 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011900 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011901 if (ordered) {
11902 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
11903 }
11904 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011905 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011906 if (ordered) {
11907 r.receiver = null;
11908 r.curFilter = null;
11909 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011910 if (filter.receiverList.app != null) {
11911 filter.receiverList.app.curReceiver = null;
11912 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011913 }
11914 }
11915 }
11916 }
11917
Dianne Hackborn12527f92009-11-11 17:39:50 -080011918 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
11919 if (r.callingUid < 0) {
11920 // This was from a registerReceiver() call; ignore it.
11921 return;
11922 }
11923 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
11924 MAX_BROADCAST_HISTORY-1);
11925 r.finishTime = SystemClock.uptimeMillis();
11926 mBroadcastHistory[0] = r;
11927 }
11928
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011929 private final void processNextBroadcast(boolean fromMsg) {
11930 synchronized(this) {
11931 BroadcastRecord r;
11932
Joe Onorato8a9b2202010-02-26 18:56:32 -080011933 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011934 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011935 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011936
11937 updateCpuStats();
11938
11939 if (fromMsg) {
11940 mBroadcastsScheduled = false;
11941 }
11942
11943 // First, deliver any non-serialized broadcasts right away.
11944 while (mParallelBroadcasts.size() > 0) {
11945 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080011946 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011947 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011948 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011949 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011950 for (int i=0; i<N; i++) {
11951 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011952 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011953 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011954 + target + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011955 deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011956 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080011957 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011958 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011959 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011960 }
11961
11962 // Now take care of the next serialized one...
11963
11964 // If we are waiting for a process to come up to handle the next
11965 // broadcast, then do nothing at this point. Just in case, we
11966 // check that the process we're waiting for still exists.
11967 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070011968 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011969 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070011970 + mPendingBroadcast.curApp);
11971 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011972
11973 boolean isDead;
11974 synchronized (mPidsSelfLocked) {
11975 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
11976 }
11977 if (!isDead) {
11978 // It's still alive, so keep waiting
11979 return;
11980 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011981 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011982 + " died before responding to broadcast");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011983 mPendingBroadcast.state = BroadcastRecord.IDLE;
11984 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011985 mPendingBroadcast = null;
11986 }
11987 }
11988
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011989 boolean looped = false;
11990
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011991 do {
11992 if (mOrderedBroadcasts.size() == 0) {
11993 // No more broadcasts pending, so all done!
11994 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011995 if (looped) {
11996 // If we had finished the last ordered broadcast, then
11997 // make sure all processes have correct oom and sched
11998 // adjustments.
11999 updateOomAdjLocked();
12000 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012001 return;
12002 }
12003 r = mOrderedBroadcasts.get(0);
12004 boolean forceReceive = false;
12005
12006 // Ensure that even if something goes awry with the timeout
12007 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050012008 // and continue to make progress.
12009 //
12010 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
Jeff Brown4d94a762010-09-23 11:33:28 -070012011 // receivers don't get executed with timeouts. They're intended for
Jeff Hamiltonacf84742010-05-25 22:10:18 -050012012 // one time heavy lifting after system upgrades and can take
12013 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012014 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012015 if (mProcessesReady && r.dispatchTime > 0) {
Jeff Hamiltonacf84742010-05-25 22:10:18 -050012016 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012017 if ((numReceivers > 0) &&
12018 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012019 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012020 + " now=" + now
12021 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080012022 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012023 + " intent=" + r.intent
12024 + " numReceivers=" + numReceivers
12025 + " nextReceiver=" + r.nextReceiver
12026 + " state=" + r.state);
Jeff Brown4d94a762010-09-23 11:33:28 -070012027 broadcastTimeoutLocked(false); // forcibly finish this broadcast
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012028 forceReceive = true;
12029 r.state = BroadcastRecord.IDLE;
12030 }
12031 }
12032
12033 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012034 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012035 "processNextBroadcast() called when not idle (state="
12036 + r.state + ")");
12037 return;
12038 }
12039
12040 if (r.receivers == null || r.nextReceiver >= numReceivers
12041 || r.resultAbort || forceReceive) {
12042 // No more receivers for this broadcast! Send the final
12043 // result if requested...
12044 if (r.resultTo != null) {
12045 try {
12046 if (DEBUG_BROADCAST) {
12047 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012048 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012049 + " seq=" + seq + " app=" + r.callerApp);
12050 }
Jeff Brown4d94a762010-09-23 11:33:28 -070012051 performReceiveLocked(r.callerApp, r.resultTo,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012052 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012053 r.resultData, r.resultExtras, false, false);
Johannes Carlssonb5a86542010-10-27 10:08:10 +020012054 // Set this to null so that the reference
12055 // (local and remote) isnt kept in the mBroadcastHistory.
12056 r.resultTo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012057 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012058 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012059 }
12060 }
12061
Joe Onorato8a9b2202010-02-26 18:56:32 -080012062 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
Jeff Brown4d94a762010-09-23 11:33:28 -070012063 cancelBroadcastTimeoutLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012064
Joe Onorato8a9b2202010-02-26 18:56:32 -080012065 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012066 + r);
12067
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012068 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080012069 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012070 mOrderedBroadcasts.remove(0);
12071 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012072 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012073 continue;
12074 }
12075 } while (r == null);
12076
12077 // Get the next receiver...
12078 int recIdx = r.nextReceiver++;
12079
12080 // Keep track of when this receiver started, and make sure there
12081 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080012082 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012083 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080012084 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012085
Joe Onorato8a9b2202010-02-26 18:56:32 -080012086 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012087 + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070012088 }
12089 if (! mPendingBroadcastTimeoutMessage) {
12090 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012091 if (DEBUG_BROADCAST) Slog.v(TAG,
Jeff Brown4d94a762010-09-23 11:33:28 -070012092 "Submitting BROADCAST_TIMEOUT_MSG for " + r + " at " + timeoutTime);
12093 setBroadcastTimeoutLocked(timeoutTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012094 }
12095
12096 Object nextReceiver = r.receivers.get(recIdx);
12097 if (nextReceiver instanceof BroadcastFilter) {
12098 // Simple case: this is a registered receiver who gets
12099 // a direct call.
12100 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012101 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070012102 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012103 + filter + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070012104 deliverToRegisteredReceiverLocked(r, filter, r.ordered);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012105 if (r.receiver == null || !r.ordered) {
12106 // The receiver has already finished, so schedule to
12107 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070012108 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
12109 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012110 r.state = BroadcastRecord.IDLE;
12111 scheduleBroadcastsLocked();
12112 }
12113 return;
12114 }
12115
12116 // Hard case: need to instantiate the receiver, possibly
12117 // starting its application process to host it.
12118
12119 ResolveInfo info =
12120 (ResolveInfo)nextReceiver;
12121
12122 boolean skip = false;
12123 int perm = checkComponentPermission(info.activityInfo.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080012124 r.callingPid, r.callingUid, info.activityInfo.applicationInfo.uid,
12125 info.activityInfo.exported);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012126 if (perm != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080012127 if (!info.activityInfo.exported) {
12128 Slog.w(TAG, "Permission Denial: broadcasting "
12129 + r.intent.toString()
12130 + " from " + r.callerPackage + " (pid=" + r.callingPid
12131 + ", uid=" + r.callingUid + ")"
12132 + " is not exported from uid " + info.activityInfo.applicationInfo.uid
12133 + " due to receiver " + info.activityInfo.packageName
12134 + "/" + info.activityInfo.name);
12135 } else {
12136 Slog.w(TAG, "Permission Denial: broadcasting "
12137 + r.intent.toString()
12138 + " from " + r.callerPackage + " (pid=" + r.callingPid
12139 + ", uid=" + r.callingUid + ")"
12140 + " requires " + info.activityInfo.permission
12141 + " due to receiver " + info.activityInfo.packageName
12142 + "/" + info.activityInfo.name);
12143 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012144 skip = true;
12145 }
12146 if (r.callingUid != Process.SYSTEM_UID &&
12147 r.requiredPermission != null) {
12148 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012149 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012150 checkPermission(r.requiredPermission,
12151 info.activityInfo.applicationInfo.packageName);
12152 } catch (RemoteException e) {
12153 perm = PackageManager.PERMISSION_DENIED;
12154 }
12155 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012156 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012157 + r.intent + " to "
12158 + info.activityInfo.applicationInfo.packageName
12159 + " requires " + r.requiredPermission
12160 + " due to sender " + r.callerPackage
12161 + " (uid " + r.callingUid + ")");
12162 skip = true;
12163 }
12164 }
12165 if (r.curApp != null && r.curApp.crashing) {
12166 // If the target process is crashing, just skip it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012167 if (DEBUG_BROADCAST) Slog.v(TAG,
12168 "Skipping deliver ordered " + r + " to " + r.curApp
12169 + ": process crashing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012170 skip = true;
12171 }
12172
12173 if (skip) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012174 if (DEBUG_BROADCAST) Slog.v(TAG,
12175 "Skipping delivery of ordered " + r + " for whatever reason");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012176 r.receiver = null;
12177 r.curFilter = null;
12178 r.state = BroadcastRecord.IDLE;
12179 scheduleBroadcastsLocked();
12180 return;
12181 }
12182
12183 r.state = BroadcastRecord.APP_RECEIVE;
12184 String targetProcess = info.activityInfo.processName;
12185 r.curComponent = new ComponentName(
12186 info.activityInfo.applicationInfo.packageName,
12187 info.activityInfo.name);
12188 r.curReceiver = info.activityInfo;
12189
Dianne Hackborne7f97212011-02-24 14:40:20 -080012190 // Broadcast is being executed, its package can't be stopped.
12191 try {
12192 AppGlobals.getPackageManager().setPackageStoppedState(
12193 r.curComponent.getPackageName(), false);
12194 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -080012195 } catch (IllegalArgumentException e) {
12196 Slog.w(TAG, "Failed trying to unstop package "
12197 + r.curComponent.getPackageName() + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -080012198 }
12199
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012200 // Is this receiver's application already running?
12201 ProcessRecord app = getProcessRecordLocked(targetProcess,
12202 info.activityInfo.applicationInfo.uid);
12203 if (app != null && app.thread != null) {
12204 try {
Dianne Hackborn6c418d52011-06-29 14:05:33 -070012205 app.addPackage(info.activityInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012206 processCurBroadcastLocked(r, app);
12207 return;
12208 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012209 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012210 + r.curComponent, e);
12211 }
12212
12213 // If a dead object exception was thrown -- fall through to
12214 // restart the application.
12215 }
12216
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012217 // Not running -- get it started, to be executed when the app comes up.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012218 if (DEBUG_BROADCAST) Slog.v(TAG,
12219 "Need to start app " + targetProcess + " for broadcast " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012220 if ((r.curApp=startProcessLocked(targetProcess,
12221 info.activityInfo.applicationInfo, true,
12222 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012223 "broadcast", r.curComponent,
12224 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
12225 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012226 // Ah, this recipient is unavailable. Finish it if necessary,
12227 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012228 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012229 + info.activityInfo.applicationInfo.packageName + "/"
12230 + info.activityInfo.applicationInfo.uid + " for broadcast "
12231 + r.intent + ": process is bad");
Jeff Brown4d94a762010-09-23 11:33:28 -070012232 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012233 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
12234 r.resultExtras, r.resultAbort, true);
12235 scheduleBroadcastsLocked();
12236 r.state = BroadcastRecord.IDLE;
12237 return;
12238 }
12239
12240 mPendingBroadcast = r;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012241 mPendingBroadcastRecvIndex = recIdx;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012242 }
12243 }
12244
12245 // =========================================================
12246 // INSTRUMENTATION
12247 // =========================================================
12248
12249 public boolean startInstrumentation(ComponentName className,
12250 String profileFile, int flags, Bundle arguments,
12251 IInstrumentationWatcher watcher) {
12252 // Refuse possible leaked file descriptors
12253 if (arguments != null && arguments.hasFileDescriptors()) {
12254 throw new IllegalArgumentException("File descriptors passed in Bundle");
12255 }
12256
12257 synchronized(this) {
12258 InstrumentationInfo ii = null;
12259 ApplicationInfo ai = null;
12260 try {
12261 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012262 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012263 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012264 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012265 } catch (PackageManager.NameNotFoundException e) {
12266 }
12267 if (ii == null) {
12268 reportStartInstrumentationFailure(watcher, className,
12269 "Unable to find instrumentation info for: " + className);
12270 return false;
12271 }
12272 if (ai == null) {
12273 reportStartInstrumentationFailure(watcher, className,
12274 "Unable to find instrumentation target package: " + ii.targetPackage);
12275 return false;
12276 }
12277
12278 int match = mContext.getPackageManager().checkSignatures(
12279 ii.targetPackage, ii.packageName);
12280 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
12281 String msg = "Permission Denial: starting instrumentation "
12282 + className + " from pid="
12283 + Binder.getCallingPid()
12284 + ", uid=" + Binder.getCallingPid()
12285 + " not allowed because package " + ii.packageName
12286 + " does not have a signature matching the target "
12287 + ii.targetPackage;
12288 reportStartInstrumentationFailure(watcher, className, msg);
12289 throw new SecurityException(msg);
12290 }
12291
12292 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012293 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012294 ProcessRecord app = addAppLocked(ai);
12295 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070012296 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012297 app.instrumentationProfileFile = profileFile;
12298 app.instrumentationArguments = arguments;
12299 app.instrumentationWatcher = watcher;
12300 app.instrumentationResultClass = className;
12301 Binder.restoreCallingIdentity(origId);
12302 }
12303
12304 return true;
12305 }
12306
12307 /**
12308 * Report errors that occur while attempting to start Instrumentation. Always writes the
12309 * error to the logs, but if somebody is watching, send the report there too. This enables
12310 * the "am" command to report errors with more information.
12311 *
12312 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
12313 * @param cn The component name of the instrumentation.
12314 * @param report The error report.
12315 */
12316 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
12317 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012318 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012319 try {
12320 if (watcher != null) {
12321 Bundle results = new Bundle();
12322 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
12323 results.putString("Error", report);
12324 watcher.instrumentationStatus(cn, -1, results);
12325 }
12326 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012327 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012328 }
12329 }
12330
12331 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
12332 if (app.instrumentationWatcher != null) {
12333 try {
12334 // NOTE: IInstrumentationWatcher *must* be oneway here
12335 app.instrumentationWatcher.instrumentationFinished(
12336 app.instrumentationClass,
12337 resultCode,
12338 results);
12339 } catch (RemoteException e) {
12340 }
12341 }
12342 app.instrumentationWatcher = null;
12343 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070012344 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012345 app.instrumentationProfileFile = null;
12346 app.instrumentationArguments = null;
12347
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012348 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012349 }
12350
12351 public void finishInstrumentation(IApplicationThread target,
12352 int resultCode, Bundle results) {
12353 // Refuse possible leaked file descriptors
12354 if (results != null && results.hasFileDescriptors()) {
12355 throw new IllegalArgumentException("File descriptors passed in Intent");
12356 }
12357
12358 synchronized(this) {
12359 ProcessRecord app = getRecordForAppLocked(target);
12360 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012361 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012362 return;
12363 }
12364 final long origId = Binder.clearCallingIdentity();
12365 finishInstrumentationLocked(app, resultCode, results);
12366 Binder.restoreCallingIdentity(origId);
12367 }
12368 }
12369
12370 // =========================================================
12371 // CONFIGURATION
12372 // =========================================================
12373
12374 public ConfigurationInfo getDeviceConfigurationInfo() {
12375 ConfigurationInfo config = new ConfigurationInfo();
12376 synchronized (this) {
12377 config.reqTouchScreen = mConfiguration.touchscreen;
12378 config.reqKeyboardType = mConfiguration.keyboard;
12379 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070012380 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
12381 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012382 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
12383 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070012384 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
12385 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012386 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
12387 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070012388 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012389 }
12390 return config;
12391 }
12392
12393 public Configuration getConfiguration() {
12394 Configuration ci;
12395 synchronized(this) {
12396 ci = new Configuration(mConfiguration);
12397 }
12398 return ci;
12399 }
12400
Dianne Hackborn31ca8542011-07-19 14:58:28 -070012401 public void updatePersistentConfiguration(Configuration values) {
12402 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
12403 "updateConfiguration()");
12404 enforceCallingPermission(android.Manifest.permission.WRITE_SETTINGS,
12405 "updateConfiguration()");
12406 if (values == null) {
12407 throw new NullPointerException("Configuration must not be null");
12408 }
12409
12410 synchronized(this) {
12411 final long origId = Binder.clearCallingIdentity();
12412 updateConfigurationLocked(values, null, true);
12413 Binder.restoreCallingIdentity(origId);
12414 }
12415 }
12416
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012417 public void updateConfiguration(Configuration values) {
12418 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
12419 "updateConfiguration()");
12420
12421 synchronized(this) {
12422 if (values == null && mWindowManager != null) {
12423 // sentinel: fetch the current configuration from the window manager
12424 values = mWindowManager.computeNewConfiguration();
12425 }
12426
12427 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn31ca8542011-07-19 14:58:28 -070012428 if (values != null) {
12429 Settings.System.clearConfiguration(values);
12430 }
12431 updateConfigurationLocked(values, null, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012432 Binder.restoreCallingIdentity(origId);
12433 }
12434 }
12435
12436 /**
12437 * Do either or both things: (1) change the current configuration, and (2)
12438 * make sure the given activity is running with the (now) current
12439 * configuration. Returns true if the activity has been left running, or
12440 * false if <var>starting</var> is being destroyed to match the new
12441 * configuration.
Dianne Hackborn31ca8542011-07-19 14:58:28 -070012442 * @param persistent TODO
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012443 */
12444 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn31ca8542011-07-19 14:58:28 -070012445 ActivityRecord starting, boolean persistent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012446 int changes = 0;
12447
12448 boolean kept = true;
12449
12450 if (values != null) {
12451 Configuration newConfig = new Configuration(mConfiguration);
12452 changes = newConfig.updateFrom(values);
12453 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070012454 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012455 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012456 }
12457
Doug Zongker2bec3d42009-12-04 12:52:44 -080012458 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012459
12460 if (values.locale != null) {
12461 saveLocaleLocked(values.locale,
12462 !values.locale.equals(mConfiguration.locale),
12463 values.userSetLocale);
12464 }
12465
Dianne Hackborne36d6e22010-02-17 19:46:25 -080012466 mConfigurationSeq++;
12467 if (mConfigurationSeq <= 0) {
12468 mConfigurationSeq = 1;
12469 }
12470 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012471 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012472 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080012473
12474 AttributeCache ac = AttributeCache.instance();
12475 if (ac != null) {
12476 ac.updateConfiguration(mConfiguration);
12477 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012478
Dianne Hackborn2f0b1752011-05-31 17:59:49 -070012479 // Make sure all resources in our process are updated
12480 // right now, so that anyone who is going to retrieve
12481 // resource values after we return will be sure to get
12482 // the new ones. This is especially important during
12483 // boot, where the first config change needs to guarantee
12484 // all resources have that config before following boot
12485 // code is executed.
12486 mSystemThread.applyConfigurationToResources(newConfig);
12487
Dianne Hackborn31ca8542011-07-19 14:58:28 -070012488 if (persistent && Settings.System.hasInterestingConfigurationChanges(changes)) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080012489 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
12490 msg.obj = new Configuration(mConfiguration);
12491 mHandler.sendMessage(msg);
12492 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012493
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012494 for (int i=mLruProcesses.size()-1; i>=0; i--) {
12495 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012496 try {
12497 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012498 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070012499 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012500 app.thread.scheduleConfigurationChanged(mConfiguration);
12501 }
12502 } catch (Exception e) {
12503 }
12504 }
12505 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012506 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
12507 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012508 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
12509 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080012510 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
12511 broadcastIntentLocked(null, null,
12512 new Intent(Intent.ACTION_LOCALE_CHANGED),
12513 null, null, 0, null, null,
12514 null, false, false, MY_PID, Process.SYSTEM_UID);
12515 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012516 }
12517 }
12518
12519 if (changes != 0 && starting == null) {
12520 // If the configuration changed, and the caller is not already
12521 // in the process of starting an activity, then find the top
12522 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012523 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012524 }
12525
12526 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012527 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
Dianne Hackborn5f4d6432010-12-21 20:40:11 -080012528 // And we need to make sure at this point that all other activities
12529 // are made visible with the correct configuration.
12530 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012531 }
12532
Dianne Hackborne36d6e22010-02-17 19:46:25 -080012533 if (values != null && mWindowManager != null) {
12534 mWindowManager.setNewConfiguration(mConfiguration);
12535 }
12536
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012537 return kept;
12538 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012539
12540 /**
12541 * Save the locale. You must be inside a synchronized (this) block.
12542 */
12543 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
12544 if(isDiff) {
12545 SystemProperties.set("user.language", l.getLanguage());
12546 SystemProperties.set("user.region", l.getCountry());
12547 }
12548
12549 if(isPersist) {
12550 SystemProperties.set("persist.sys.language", l.getLanguage());
12551 SystemProperties.set("persist.sys.country", l.getCountry());
12552 SystemProperties.set("persist.sys.localevar", l.getVariant());
12553 }
12554 }
12555
12556 // =========================================================
12557 // LIFETIME MANAGEMENT
12558 // =========================================================
12559
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012560 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
12561 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012562 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012563 // This adjustment has already been computed. If we are calling
12564 // from the top, we may have already computed our adjustment with
12565 // an earlier hidden adjustment that isn't really for us... if
12566 // so, use the new hidden adjustment.
12567 if (!recursed && app.hidden) {
12568 app.curAdj = hiddenAdj;
12569 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012570 return app.curAdj;
12571 }
12572
12573 if (app.thread == null) {
12574 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012575 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012576 return (app.curAdj=EMPTY_APP_ADJ);
12577 }
12578
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012579 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
12580 // The max adjustment doesn't allow this app to be anything
12581 // below foreground, so it is not worth doing work for it.
12582 app.adjType = "fixed";
12583 app.adjSeq = mAdjSeq;
12584 app.curRawAdj = app.maxAdj;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012585 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012586 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
12587 return (app.curAdj=app.maxAdj);
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012588 }
12589
12590 final boolean hadForegroundActivities = app.foregroundActivities;
12591
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012592 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012593 app.adjSource = null;
12594 app.adjTarget = null;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012595 app.keeping = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012596 app.empty = false;
12597 app.hidden = false;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012598 app.foregroundActivities = false;
12599
12600 final int activitiesSize = app.activities.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012601
The Android Open Source Project4df24232009-03-05 14:34:35 -080012602 // Determine the importance of the process, starting with most
12603 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012604 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012605 int schedGroup;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012606 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012607 // The last app on the list is the foreground app.
12608 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012609 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012610 app.adjType = "top-activity";
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012611 app.foregroundActivities = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012612 } else if (app.instrumentationClass != null) {
12613 // Don't want to kill running instrumentation.
12614 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012615 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012616 app.adjType = "instrumentation";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012617 } else if (app.curReceiver != null ||
12618 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
12619 // An app that is currently receiving a broadcast also
12620 // counts as being in the foreground.
12621 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012622 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012623 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012624 } else if (app.executingServices.size() > 0) {
12625 // An app that is currently executing a service callback also
12626 // counts as being in the foreground.
12627 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012628 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012629 app.adjType = "exec-service";
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012630 } else if (activitiesSize > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012631 // This app is in the background with paused activities.
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012632 // We inspect activities to potentially upgrade adjustment further below.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012633 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012634 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012635 app.hidden = true;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012636 app.adjType = "bg-activities";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012637 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012638 // A very not-needed process. If this is lower in the lru list,
12639 // we will push it in to the empty bucket.
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012640 adj = hiddenAdj;
12641 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012642 app.hidden = true;
12643 app.empty = true;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012644 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012645 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012646
12647 // Examine all activities if not already foreground.
12648 if (!app.foregroundActivities && activitiesSize > 0) {
12649 for (int j = 0; j < activitiesSize; j++) {
12650 final ActivityRecord r = app.activities.get(j);
12651 if (r.visible) {
12652 // App has a visible activity; only upgrade adjustment.
12653 if (adj > VISIBLE_APP_ADJ) {
12654 adj = VISIBLE_APP_ADJ;
12655 app.adjType = "visible";
12656 }
12657 schedGroup = Process.THREAD_GROUP_DEFAULT;
12658 app.hidden = false;
12659 app.foregroundActivities = true;
12660 break;
12661 } else if (r.state == ActivityState.PAUSING || r.state == ActivityState.PAUSED
12662 || r.state == ActivityState.STOPPING) {
12663 // Only upgrade adjustment.
12664 if (adj > PERCEPTIBLE_APP_ADJ) {
12665 adj = PERCEPTIBLE_APP_ADJ;
12666 app.adjType = "stopping";
12667 }
12668 app.foregroundActivities = true;
12669 }
12670 }
12671 }
12672
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012673 if (adj > PERCEPTIBLE_APP_ADJ) {
12674 if (app.foregroundServices) {
12675 // The user is aware of this app, so make it visible.
12676 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012677 app.adjType = "foreground-service";
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012678 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012679 } else if (app.forcingToForeground != null) {
12680 // The user is aware of this app, so make it visible.
12681 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012682 app.adjType = "force-foreground";
12683 app.adjSource = app.forcingToForeground;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012684 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012685 }
12686 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012687
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012688 if (adj > HEAVY_WEIGHT_APP_ADJ && app == mHeavyWeightProcess) {
12689 // We don't want to kill the current heavy-weight process.
12690 adj = HEAVY_WEIGHT_APP_ADJ;
12691 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
12692 app.adjType = "heavy";
12693 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012694
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012695 if (adj > HOME_APP_ADJ && app == mHomeProcess) {
12696 // This process is hosting what we currently consider to be the
12697 // home app, so we don't want to let it go into the background.
12698 adj = HOME_APP_ADJ;
12699 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
12700 app.adjType = "home";
12701 }
12702
Joe Onorato8a9b2202010-02-26 18:56:32 -080012703 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012704
The Android Open Source Project4df24232009-03-05 14:34:35 -080012705 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012706 // there are applications dependent on our services or providers, but
12707 // this gives us a baseline and makes sure we don't get into an
12708 // infinite recursion.
12709 app.adjSeq = mAdjSeq;
12710 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012711
Christopher Tate6fa95972009-06-05 18:43:55 -070012712 if (mBackupTarget != null && app == mBackupTarget.app) {
12713 // If possible we want to avoid killing apps while they're being backed up
12714 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012715 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070012716 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012717 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012718 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070012719 }
12720 }
12721
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012722 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
12723 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012724 final long now = SystemClock.uptimeMillis();
12725 // This process is more important if the top activity is
12726 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070012727 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012728 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012729 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012730 if (s.startRequested) {
12731 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
12732 // This service has seen some activity within
12733 // recent memory, so we will keep its process ahead
12734 // of the background processes.
12735 if (adj > SECONDARY_SERVER_ADJ) {
12736 adj = SECONDARY_SERVER_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012737 app.adjType = "started-services";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012738 app.hidden = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012739 }
12740 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012741 // If we have let the service slide into the background
12742 // state, still have some text describing what it is doing
12743 // even though the service no longer has an impact.
12744 if (adj > SECONDARY_SERVER_ADJ) {
12745 app.adjType = "started-bg-services";
12746 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012747 // Don't kill this process because it is doing work; it
12748 // has said it is doing work.
12749 app.keeping = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012750 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012751 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
12752 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012753 Iterator<ArrayList<ConnectionRecord>> kt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012754 = s.connections.values().iterator();
12755 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012756 ArrayList<ConnectionRecord> clist = kt.next();
12757 for (int i=0; i<clist.size() && adj > FOREGROUND_APP_ADJ; i++) {
12758 // XXX should compute this based on the max of
12759 // all connected clients.
12760 ConnectionRecord cr = clist.get(i);
12761 if (cr.binding.client == app) {
12762 // Binding to ourself is not interesting.
12763 continue;
12764 }
12765 if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
12766 ProcessRecord client = cr.binding.client;
12767 int myHiddenAdj = hiddenAdj;
12768 if (myHiddenAdj > client.hiddenAdj) {
12769 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
12770 myHiddenAdj = client.hiddenAdj;
12771 } else {
12772 myHiddenAdj = VISIBLE_APP_ADJ;
12773 }
12774 }
12775 int clientAdj = computeOomAdjLocked(
12776 client, myHiddenAdj, TOP_APP, true);
12777 if (adj > clientAdj) {
12778 adj = clientAdj >= VISIBLE_APP_ADJ
12779 ? clientAdj : VISIBLE_APP_ADJ;
12780 if (!client.hidden) {
12781 app.hidden = false;
12782 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012783 if (client.keeping) {
12784 app.keeping = true;
12785 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012786 app.adjType = "service";
12787 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12788 .REASON_SERVICE_IN_USE;
12789 app.adjSource = cr.binding.client;
12790 app.adjTarget = s.name;
12791 }
12792 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
12793 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
12794 schedGroup = Process.THREAD_GROUP_DEFAULT;
12795 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012796 }
12797 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012798 ActivityRecord a = cr.activity;
12799 //if (a != null) {
12800 // Slog.i(TAG, "Connection to " + a ": state=" + a.state);
12801 //}
12802 if (a != null && adj > FOREGROUND_APP_ADJ &&
12803 (a.state == ActivityState.RESUMED
12804 || a.state == ActivityState.PAUSING)) {
12805 adj = FOREGROUND_APP_ADJ;
12806 schedGroup = Process.THREAD_GROUP_DEFAULT;
12807 app.hidden = false;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012808 app.adjType = "service";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012809 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12810 .REASON_SERVICE_IN_USE;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012811 app.adjSource = a;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012812 app.adjTarget = s.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012813 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012814 }
12815 }
12816 }
12817 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012818
Dianne Hackborn287952c2010-09-22 22:34:31 -070012819 // Finally, if this process has active services running in it, we
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012820 // would like to avoid killing it unless it would prevent the current
12821 // application from running. By default we put the process in
12822 // with the rest of the background processes; as we scan through
12823 // its services we may bump it up from there.
12824 if (adj > hiddenAdj) {
12825 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012826 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012827 app.adjType = "bg-services";
12828 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012829 }
12830
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012831 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
12832 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012833 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012834 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
12835 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012836 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012837 if (cpr.clients.size() != 0) {
12838 Iterator<ProcessRecord> kt = cpr.clients.iterator();
12839 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
12840 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070012841 if (client == app) {
12842 // Being our own client is not interesting.
12843 continue;
12844 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012845 int myHiddenAdj = hiddenAdj;
12846 if (myHiddenAdj > client.hiddenAdj) {
12847 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
12848 myHiddenAdj = client.hiddenAdj;
12849 } else {
12850 myHiddenAdj = FOREGROUND_APP_ADJ;
12851 }
12852 }
12853 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012854 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012855 if (adj > clientAdj) {
12856 adj = clientAdj > FOREGROUND_APP_ADJ
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012857 ? clientAdj : FOREGROUND_APP_ADJ;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012858 if (!client.hidden) {
12859 app.hidden = false;
12860 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012861 if (client.keeping) {
12862 app.keeping = true;
12863 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012864 app.adjType = "provider";
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012865 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12866 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012867 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012868 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012869 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012870 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
12871 schedGroup = Process.THREAD_GROUP_DEFAULT;
12872 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012873 }
12874 }
12875 // If the provider has external (non-framework) process
12876 // dependencies, ensure that its adjustment is at least
12877 // FOREGROUND_APP_ADJ.
12878 if (cpr.externals != 0) {
12879 if (adj > FOREGROUND_APP_ADJ) {
12880 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012881 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012882 app.hidden = false;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012883 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012884 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012885 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012886 }
12887 }
12888 }
12889 }
12890
12891 app.curRawAdj = adj;
12892
Joe Onorato8a9b2202010-02-26 18:56:32 -080012893 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012894 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
12895 if (adj > app.maxAdj) {
12896 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070012897 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012898 schedGroup = Process.THREAD_GROUP_DEFAULT;
12899 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012900 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012901 if (adj < HIDDEN_APP_MIN_ADJ) {
12902 app.keeping = true;
12903 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012904
12905 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012906 app.curSchedGroup = schedGroup;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012907
12908 if (hadForegroundActivities != app.foregroundActivities) {
Jeff Sharkey287bd832011-05-28 19:36:26 -070012909 mHandler.obtainMessage(DISPATCH_FOREGROUND_ACTIVITIES_CHANGED, app.pid, app.info.uid,
12910 app.foregroundActivities).sendToTarget();
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012911 }
12912
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012913 return adj;
12914 }
12915
12916 /**
12917 * Ask a given process to GC right now.
12918 */
12919 final void performAppGcLocked(ProcessRecord app) {
12920 try {
12921 app.lastRequestedGc = SystemClock.uptimeMillis();
12922 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012923 if (app.reportLowMemory) {
12924 app.reportLowMemory = false;
12925 app.thread.scheduleLowMemory();
12926 } else {
12927 app.thread.processInBackground();
12928 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012929 }
12930 } catch (Exception e) {
12931 // whatever.
12932 }
12933 }
12934
12935 /**
12936 * Returns true if things are idle enough to perform GCs.
12937 */
Josh Bartel7f208742010-02-25 11:01:44 -060012938 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012939 return mParallelBroadcasts.size() == 0
12940 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012941 && (mSleeping || (mMainStack.mResumedActivity != null &&
12942 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012943 }
12944
12945 /**
12946 * Perform GCs on all processes that are waiting for it, but only
12947 * if things are idle.
12948 */
12949 final void performAppGcsLocked() {
12950 final int N = mProcessesToGc.size();
12951 if (N <= 0) {
12952 return;
12953 }
Josh Bartel7f208742010-02-25 11:01:44 -060012954 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012955 while (mProcessesToGc.size() > 0) {
12956 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070012957 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012958 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
12959 <= SystemClock.uptimeMillis()) {
12960 // To avoid spamming the system, we will GC processes one
12961 // at a time, waiting a few seconds between each.
12962 performAppGcLocked(proc);
12963 scheduleAppGcsLocked();
12964 return;
12965 } else {
12966 // It hasn't been long enough since we last GCed this
12967 // process... put it in the list to wait for its time.
12968 addProcessToGcListLocked(proc);
12969 break;
12970 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012971 }
12972 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012973
12974 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012975 }
12976 }
12977
12978 /**
12979 * If all looks good, perform GCs on all processes waiting for them.
12980 */
12981 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060012982 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012983 performAppGcsLocked();
12984 return;
12985 }
12986 // Still not idle, wait some more.
12987 scheduleAppGcsLocked();
12988 }
12989
12990 /**
12991 * Schedule the execution of all pending app GCs.
12992 */
12993 final void scheduleAppGcsLocked() {
12994 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012995
12996 if (mProcessesToGc.size() > 0) {
12997 // Schedule a GC for the time to the next process.
12998 ProcessRecord proc = mProcessesToGc.get(0);
12999 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
13000
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013001 long when = proc.lastRequestedGc + GC_MIN_INTERVAL;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013002 long now = SystemClock.uptimeMillis();
13003 if (when < (now+GC_TIMEOUT)) {
13004 when = now + GC_TIMEOUT;
13005 }
13006 mHandler.sendMessageAtTime(msg, when);
13007 }
13008 }
13009
13010 /**
13011 * Add a process to the array of processes waiting to be GCed. Keeps the
13012 * list in sorted order by the last GC time. The process can't already be
13013 * on the list.
13014 */
13015 final void addProcessToGcListLocked(ProcessRecord proc) {
13016 boolean added = false;
13017 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
13018 if (mProcessesToGc.get(i).lastRequestedGc <
13019 proc.lastRequestedGc) {
13020 added = true;
13021 mProcessesToGc.add(i+1, proc);
13022 break;
13023 }
13024 }
13025 if (!added) {
13026 mProcessesToGc.add(0, proc);
13027 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013028 }
13029
13030 /**
13031 * Set up to ask a process to GC itself. This will either do it
13032 * immediately, or put it on the list of processes to gc the next
13033 * time things are idle.
13034 */
13035 final void scheduleAppGcLocked(ProcessRecord app) {
13036 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013037 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013038 return;
13039 }
13040 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013041 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013042 scheduleAppGcsLocked();
13043 }
13044 }
13045
Dianne Hackborn287952c2010-09-22 22:34:31 -070013046 final void checkExcessivePowerUsageLocked(boolean doKills) {
13047 updateCpuStatsNow();
13048
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013049 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
Dianne Hackborn287952c2010-09-22 22:34:31 -070013050 boolean doWakeKills = doKills;
13051 boolean doCpuKills = doKills;
13052 if (mLastPowerCheckRealtime == 0) {
13053 doWakeKills = false;
13054 }
13055 if (mLastPowerCheckUptime == 0) {
13056 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013057 }
13058 if (stats.isScreenOn()) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070013059 doWakeKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013060 }
13061 final long curRealtime = SystemClock.elapsedRealtime();
Dianne Hackborn287952c2010-09-22 22:34:31 -070013062 final long realtimeSince = curRealtime - mLastPowerCheckRealtime;
13063 final long curUptime = SystemClock.uptimeMillis();
13064 final long uptimeSince = curUptime - mLastPowerCheckUptime;
13065 mLastPowerCheckRealtime = curRealtime;
13066 mLastPowerCheckUptime = curUptime;
13067 if (realtimeSince < WAKE_LOCK_MIN_CHECK_DURATION) {
13068 doWakeKills = false;
13069 }
13070 if (uptimeSince < CPU_MIN_CHECK_DURATION) {
13071 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013072 }
13073 int i = mLruProcesses.size();
13074 while (i > 0) {
13075 i--;
13076 ProcessRecord app = mLruProcesses.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -070013077 if (!app.keeping) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013078 long wtime;
13079 synchronized (stats) {
13080 wtime = stats.getProcessWakeTime(app.info.uid,
13081 app.pid, curRealtime);
13082 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070013083 long wtimeUsed = wtime - app.lastWakeTime;
13084 long cputimeUsed = app.curCpuTime - app.lastCpuTime;
13085 if (DEBUG_POWER) {
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070013086 StringBuilder sb = new StringBuilder(128);
13087 sb.append("Wake for ");
13088 app.toShortString(sb);
13089 sb.append(": over ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070013090 TimeUtils.formatDuration(realtimeSince, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070013091 sb.append(" used ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070013092 TimeUtils.formatDuration(wtimeUsed, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070013093 sb.append(" (");
Dianne Hackborn287952c2010-09-22 22:34:31 -070013094 sb.append((wtimeUsed*100)/realtimeSince);
13095 sb.append("%)");
13096 Slog.i(TAG, sb.toString());
13097 sb.setLength(0);
13098 sb.append("CPU for ");
13099 app.toShortString(sb);
13100 sb.append(": over ");
13101 TimeUtils.formatDuration(uptimeSince, sb);
13102 sb.append(" used ");
13103 TimeUtils.formatDuration(cputimeUsed, sb);
13104 sb.append(" (");
13105 sb.append((cputimeUsed*100)/uptimeSince);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070013106 sb.append("%)");
13107 Slog.i(TAG, sb.toString());
13108 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013109 // If a process has held a wake lock for more
13110 // than 50% of the time during this period,
13111 // that sounds pad. Kill!
Dianne Hackborn287952c2010-09-22 22:34:31 -070013112 if (doWakeKills && realtimeSince > 0
13113 && ((wtimeUsed*100)/realtimeSince) >= 50) {
13114 synchronized (stats) {
13115 stats.reportExcessiveWakeLocked(app.info.uid, app.processName,
13116 realtimeSince, wtimeUsed);
13117 }
13118 Slog.w(TAG, "Excessive wake lock in " + app.processName
13119 + " (pid " + app.pid + "): held " + wtimeUsed
13120 + " during " + realtimeSince);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013121 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13122 app.processName, app.setAdj, "excessive wake lock");
13123 Process.killProcessQuiet(app.pid);
Dianne Hackborn287952c2010-09-22 22:34:31 -070013124 } else if (doCpuKills && uptimeSince > 0
13125 && ((cputimeUsed*100)/uptimeSince) >= 50) {
13126 synchronized (stats) {
13127 stats.reportExcessiveCpuLocked(app.info.uid, app.processName,
13128 uptimeSince, cputimeUsed);
13129 }
13130 Slog.w(TAG, "Excessive CPU in " + app.processName
13131 + " (pid " + app.pid + "): used " + cputimeUsed
13132 + " during " + uptimeSince);
13133 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13134 app.processName, app.setAdj, "excessive cpu");
13135 Process.killProcessQuiet(app.pid);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013136 } else {
13137 app.lastWakeTime = wtime;
Dianne Hackborn287952c2010-09-22 22:34:31 -070013138 app.lastCpuTime = app.curCpuTime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013139 }
13140 }
13141 }
13142 }
13143
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013144 private final void updateOomAdjLocked(
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013145 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013146 app.hiddenAdj = hiddenAdj;
13147
13148 if (app.thread == null) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013149 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013150 }
13151
Dianne Hackborn287952c2010-09-22 22:34:31 -070013152 final boolean wasKeeping = app.keeping;
13153
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013154 int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013155
Jeff Brown10e89712011-07-08 18:52:57 -070013156 if (app.curRawAdj != app.setRawAdj) {
13157 if (app.curRawAdj > FOREGROUND_APP_ADJ
13158 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
13159 // If this app is transitioning from foreground to
13160 // non-foreground, have it do a gc.
13161 scheduleAppGcLocked(app);
13162 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
13163 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
13164 // Likewise do a gc when an app is moving in to the
13165 // background (such as a service stopping).
13166 scheduleAppGcLocked(app);
13167 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070013168
Jeff Brown10e89712011-07-08 18:52:57 -070013169 if (wasKeeping && !app.keeping) {
13170 // This app is no longer something we want to keep. Note
13171 // its current wake lock time to later know to kill it if
13172 // it is not behaving well.
13173 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
13174 synchronized (stats) {
13175 app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
13176 app.pid, SystemClock.elapsedRealtime());
13177 }
13178 app.lastCpuTime = app.curCpuTime;
13179 }
13180
13181 app.setRawAdj = app.curRawAdj;
13182 }
13183 if (adj != app.setAdj) {
13184 if (Process.setOomAdj(app.pid, adj)) {
13185 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
13186 TAG, "Set app " + app.processName +
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013187 " oom adj to " + adj + " because " + app.adjType);
Jeff Brown10e89712011-07-08 18:52:57 -070013188 app.setAdj = adj;
13189 } else {
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013190 Slog.w(TAG, "Failed setting oom adj of " + app + " to " + adj);
Jeff Brown10e89712011-07-08 18:52:57 -070013191 }
13192 }
13193 if (app.setSchedGroup != app.curSchedGroup) {
13194 app.setSchedGroup = app.curSchedGroup;
13195 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
13196 "Setting process group of " + app.processName
13197 + " to " + app.curSchedGroup);
13198 if (app.waitingToKill != null &&
13199 app.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {
13200 Slog.i(TAG, "Killing " + app.toShortString() + ": " + app.waitingToKill);
13201 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13202 app.processName, app.setAdj, app.waitingToKill);
13203 Process.killProcessQuiet(app.pid);
13204 } else {
13205 if (true) {
13206 long oldId = Binder.clearCallingIdentity();
13207 try {
13208 Process.setProcessGroup(app.pid, app.curSchedGroup);
13209 } catch (Exception e) {
13210 Slog.w(TAG, "Failed setting process group of " + app.pid
13211 + " to " + app.curSchedGroup);
13212 e.printStackTrace();
13213 } finally {
13214 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013215 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013216 } else {
Jeff Brown10e89712011-07-08 18:52:57 -070013217 if (app.thread != null) {
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013218 try {
Jeff Brown10e89712011-07-08 18:52:57 -070013219 app.thread.setSchedulingGroup(app.curSchedGroup);
13220 } catch (RemoteException e) {
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013221 }
13222 }
13223 }
13224 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013225 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013226 }
13227
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013228 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013229 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013230 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013231 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013232 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013233 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013234 }
13235 }
13236 return resumedActivity;
13237 }
13238
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013239 private final void updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013240 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013241 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
13242 int curAdj = app.curAdj;
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013243 final boolean wasHidden = curAdj >= HIDDEN_APP_MIN_ADJ
13244 && curAdj <= HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013245
13246 mAdjSeq++;
13247
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013248 updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
13249 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
13250 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
13251 if (nowHidden != wasHidden) {
13252 // Changed to/from hidden state, so apps after it in the LRU
13253 // list may also be changed.
13254 updateOomAdjLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013255 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013256 }
13257
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013258 final void updateOomAdjLocked() {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013259 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013260 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
13261
13262 if (false) {
13263 RuntimeException e = new RuntimeException();
13264 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080013265 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013266 }
13267
13268 mAdjSeq++;
13269
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013270 // Let's determine how many processes we have running vs.
13271 // how many slots we have for background processes; we may want
13272 // to put multiple processes in a slot of there are enough of
13273 // them.
13274 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
13275 int factor = (mLruProcesses.size()-4)/numSlots;
13276 if (factor < 1) factor = 1;
13277 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070013278 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013279
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013280 // First update the OOM adjustment for each of the
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013281 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013282 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013283 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013284 int numBg = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013285 while (i > 0) {
13286 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013287 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013288 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013289 updateOomAdjLocked(app, curHiddenAdj, TOP_APP);
13290 if (curHiddenAdj < EMPTY_APP_ADJ
13291 && app.curAdj == curHiddenAdj) {
13292 step++;
13293 if (step >= factor) {
13294 step = 0;
13295 curHiddenAdj++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013296 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013297 }
13298 if (!app.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -070013299 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013300 numHidden++;
13301 if (numHidden > mProcessLimit) {
13302 Slog.i(TAG, "No longer want " + app.processName
13303 + " (pid " + app.pid + "): hidden #" + numHidden);
13304 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13305 app.processName, app.setAdj, "too many background");
13306 app.killedBackground = true;
13307 Process.killProcessQuiet(app.pid);
13308 } else {
13309 numBg++;
Dianne Hackborn8633e682010-04-22 16:03:41 -070013310 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013311 } else if (app.curAdj >= HOME_APP_ADJ) {
13312 numBg++;
Dianne Hackborn8633e682010-04-22 16:03:41 -070013313 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013314 }
13315 }
13316
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013317 // Now determine the memory trimming level of background processes.
13318 // Unfortunately we need to start at the back of the list to do this
13319 // properly. We only do this if the number of background apps we
13320 // are managing to keep around is less than half the maximum we desire;
13321 // if we are keeping a good number around, we'll let them use whatever
13322 // memory they want.
13323 if (numHidden <= (MAX_HIDDEN_APPS/2)) {
13324 final int N = mLruProcesses.size();
13325 factor = numBg/3;
13326 step = 0;
13327 int curLevel = ComponentCallbacks.TRIM_MEMORY_COMPLETE;
13328 for (i=0; i<N; i++) {
13329 ProcessRecord app = mLruProcesses.get(i);
13330 if (app.curAdj >= HIDDEN_APP_MIN_ADJ && !app.killedBackground) {
13331 if (app.trimMemoryLevel < curLevel && app.thread != null) {
13332 try {
13333 app.thread.scheduleTrimMemory(curLevel);
13334 } catch (RemoteException e) {
13335 }
13336 if (curLevel >= ComponentCallbacks.TRIM_MEMORY_COMPLETE) {
13337 // For these apps we will also finish their activities
13338 // to help them free memory.
13339 mMainStack.destroyActivitiesLocked(app, false);
13340 }
13341 }
13342 app.trimMemoryLevel = curLevel;
13343 step++;
13344 if (step >= factor) {
13345 switch (curLevel) {
13346 case ComponentCallbacks.TRIM_MEMORY_COMPLETE:
13347 curLevel = ComponentCallbacks.TRIM_MEMORY_MODERATE;
13348 break;
13349 case ComponentCallbacks.TRIM_MEMORY_MODERATE:
13350 curLevel = ComponentCallbacks.TRIM_MEMORY_BACKGROUND;
13351 break;
13352 }
13353 }
13354 } else if (app.curAdj >= PERCEPTIBLE_APP_ADJ) {
13355 if (app.trimMemoryLevel < ComponentCallbacks.TRIM_MEMORY_INVISIBLE
13356 && app.thread != null) {
13357 try {
13358 app.thread.scheduleTrimMemory(ComponentCallbacks.TRIM_MEMORY_INVISIBLE);
13359 } catch (RemoteException e) {
13360 }
13361 }
13362 app.trimMemoryLevel = ComponentCallbacks.TRIM_MEMORY_INVISIBLE;
13363 } else {
13364 app.trimMemoryLevel = 0;
13365 }
13366 }
13367 } else {
13368 final int N = mLruProcesses.size();
13369 for (i=0; i<N; i++) {
13370 ProcessRecord app = mLruProcesses.get(i);
13371 app.trimMemoryLevel = 0;
13372 }
13373 }
13374
13375 if (mAlwaysFinishActivities) {
13376 mMainStack.destroyActivitiesLocked(null, false);
13377 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013378 }
13379
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013380 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013381 synchronized (this) {
13382 int i;
13383
13384 // First remove any unused application processes whose package
13385 // has been removed.
13386 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
13387 final ProcessRecord app = mRemovedProcesses.get(i);
13388 if (app.activities.size() == 0
13389 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013390 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013391 TAG, "Exiting empty application process "
13392 + app.processName + " ("
13393 + (app.thread != null ? app.thread.asBinder() : null)
13394 + ")\n");
13395 if (app.pid > 0 && app.pid != MY_PID) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070013396 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13397 app.processName, app.setAdj, "empty");
13398 Process.killProcessQuiet(app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013399 } else {
13400 try {
13401 app.thread.scheduleExit();
13402 } catch (Exception e) {
13403 // Ignore exceptions.
13404 }
13405 }
13406 cleanUpApplicationRecordLocked(app, false, -1);
13407 mRemovedProcesses.remove(i);
13408
13409 if (app.persistent) {
13410 if (app.persistent) {
13411 addAppLocked(app.info);
13412 }
13413 }
13414 }
13415 }
13416
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013417 // Now update the oom adj for all processes.
13418 updateOomAdjLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013419 }
13420 }
13421
13422 /** This method sends the specified signal to each of the persistent apps */
13423 public void signalPersistentProcesses(int sig) throws RemoteException {
13424 if (sig != Process.SIGNAL_USR1) {
13425 throw new SecurityException("Only SIGNAL_USR1 is allowed");
13426 }
13427
13428 synchronized (this) {
13429 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
13430 != PackageManager.PERMISSION_GRANTED) {
13431 throw new SecurityException("Requires permission "
13432 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
13433 }
13434
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013435 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
13436 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013437 if (r.thread != null && r.persistent) {
13438 Process.sendSignal(r.pid, sig);
13439 }
13440 }
13441 }
13442 }
13443
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013444 public boolean profileControl(String process, boolean start,
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013445 String path, ParcelFileDescriptor fd) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013446
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013447 try {
13448 synchronized (this) {
13449 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
13450 // its own permission.
13451 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
13452 != PackageManager.PERMISSION_GRANTED) {
13453 throw new SecurityException("Requires permission "
13454 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013455 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013456
13457 if (start && fd == null) {
13458 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013459 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013460
13461 ProcessRecord proc = null;
13462 try {
13463 int pid = Integer.parseInt(process);
13464 synchronized (mPidsSelfLocked) {
13465 proc = mPidsSelfLocked.get(pid);
13466 }
13467 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013468 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013469
13470 if (proc == null) {
13471 HashMap<String, SparseArray<ProcessRecord>> all
13472 = mProcessNames.getMap();
13473 SparseArray<ProcessRecord> procs = all.get(process);
13474 if (procs != null && procs.size() > 0) {
13475 proc = procs.valueAt(0);
13476 }
13477 }
13478
13479 if (proc == null || proc.thread == null) {
13480 throw new IllegalArgumentException("Unknown process: " + process);
13481 }
13482
Dianne Hackbornf02e57b2011-03-01 22:21:04 -080013483 boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
13484 if (!isDebuggable) {
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013485 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
13486 throw new SecurityException("Process not debuggable: " + proc);
13487 }
13488 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013489
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013490 proc.thread.profilerControl(start, path, fd);
13491 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013492 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013493 }
13494 } catch (RemoteException e) {
13495 throw new IllegalStateException("Process disappeared");
13496 } finally {
13497 if (fd != null) {
13498 try {
13499 fd.close();
13500 } catch (IOException e) {
13501 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013502 }
13503 }
13504 }
Andy McFadden824c5102010-07-09 16:26:57 -070013505
13506 public boolean dumpHeap(String process, boolean managed,
13507 String path, ParcelFileDescriptor fd) throws RemoteException {
13508
13509 try {
13510 synchronized (this) {
13511 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
13512 // its own permission (same as profileControl).
13513 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
13514 != PackageManager.PERMISSION_GRANTED) {
13515 throw new SecurityException("Requires permission "
13516 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
13517 }
13518
13519 if (fd == null) {
13520 throw new IllegalArgumentException("null fd");
13521 }
13522
13523 ProcessRecord proc = null;
13524 try {
13525 int pid = Integer.parseInt(process);
13526 synchronized (mPidsSelfLocked) {
13527 proc = mPidsSelfLocked.get(pid);
13528 }
13529 } catch (NumberFormatException e) {
13530 }
13531
13532 if (proc == null) {
13533 HashMap<String, SparseArray<ProcessRecord>> all
13534 = mProcessNames.getMap();
13535 SparseArray<ProcessRecord> procs = all.get(process);
13536 if (procs != null && procs.size() > 0) {
13537 proc = procs.valueAt(0);
13538 }
13539 }
13540
13541 if (proc == null || proc.thread == null) {
13542 throw new IllegalArgumentException("Unknown process: " + process);
13543 }
13544
Dianne Hackbornf02e57b2011-03-01 22:21:04 -080013545 boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
13546 if (!isDebuggable) {
Andy McFadden824c5102010-07-09 16:26:57 -070013547 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
13548 throw new SecurityException("Process not debuggable: " + proc);
13549 }
13550 }
13551
13552 proc.thread.dumpHeap(managed, path, fd);
13553 fd = null;
13554 return true;
13555 }
13556 } catch (RemoteException e) {
13557 throw new IllegalStateException("Process disappeared");
13558 } finally {
13559 if (fd != null) {
13560 try {
13561 fd.close();
13562 } catch (IOException e) {
13563 }
13564 }
13565 }
13566 }
13567
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013568 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
13569 public void monitor() {
13570 synchronized (this) { }
13571 }
Svetoslav Ganov54d068e2011-03-02 12:58:40 -080013572
13573 public void onCoreSettingsChange(Bundle settings) {
13574 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
13575 ProcessRecord processRecord = mLruProcesses.get(i);
13576 try {
13577 if (processRecord.thread != null) {
13578 processRecord.thread.setCoreSettings(settings);
13579 }
13580 } catch (RemoteException re) {
13581 /* ignore */
13582 }
13583 }
13584 }
Amith Yamasani4b2e9342011-03-31 12:38:53 -070013585
13586 // Multi-user methods
13587
13588 public boolean switchUser(int userid) {
13589 // TODO
13590 return true;
13591 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013592}