blob: 14c63062680b65f3f3b428d261407e240161f864 [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 Hackbornc68c9132011-07-29 01:25:18 -070056import android.content.ComponentCallbacks2;
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);
Dianne Hackborn130b0d22011-07-26 22:07:48 -07001824 handleAppDiedLocked(app, true, true);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001825 }
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,
Dianne Hackborn130b0d22011-07-26 22:07:48 -07002661 boolean restarting, boolean allowRestart) {
2662 cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002663 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;
Dianne Hackborn130b0d22011-07-26 22:07:48 -07002794 handleAppDiedLocked(app, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002795
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 Hackborn130b0d22011-07-26 22:07:48 -07003198 SECONDARY_SERVER_ADJ, false, true, 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,
Dianne Hackborn130b0d22011-07-26 22:07:48 -07003361 int minOomAdj, boolean callerWillRestart, boolean allowRestart, boolean doit) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003362 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003363
Dianne Hackborn03abb812010-01-04 18:43:19 -08003364 // Remove all processes this package may have touched: all with the
3365 // same UID (except for the system or root user), and all whose name
3366 // matches the package name.
3367 final String procNamePrefix = packageName + ":";
3368 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
3369 final int NA = apps.size();
3370 for (int ia=0; ia<NA; ia++) {
3371 ProcessRecord app = apps.valueAt(ia);
Christopher Tate064d8422011-07-26 15:38:07 -07003372 if (app.persistent) {
3373 // we don't kill persistent processes
3374 continue;
3375 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003376 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003377 if (doit) {
3378 procs.add(app);
3379 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003380 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
3381 || app.processName.equals(packageName)
3382 || app.processName.startsWith(procNamePrefix)) {
3383 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003384 if (!doit) {
3385 return true;
3386 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003387 app.removed = true;
3388 procs.add(app);
3389 }
3390 }
3391 }
3392 }
3393
3394 int N = procs.size();
3395 for (int i=0; i<N; i++) {
Dianne Hackborn130b0d22011-07-26 22:07:48 -07003396 removeProcessLocked(procs.get(i), callerWillRestart, allowRestart);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003397 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003398 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08003399 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003400
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003401 private final boolean forceStopPackageLocked(String name, int uid,
3402 boolean callerWillRestart, boolean purgeCache, boolean doit) {
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07003403 int i;
3404 int N;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003405
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003406 if (uid < 0) {
3407 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003408 uid = AppGlobals.getPackageManager().getPackageUid(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003409 } catch (RemoteException e) {
3410 }
3411 }
3412
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003413 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003414 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003415
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003416 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
3417 while (badApps.hasNext()) {
3418 SparseArray<Long> ba = badApps.next();
3419 if (ba.get(uid) != null) {
3420 badApps.remove();
3421 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003422 }
3423 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003424
3425 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
Dianne Hackborn130b0d22011-07-26 22:07:48 -07003426 callerWillRestart, false, doit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003427
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003428 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3429 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Christopher Tate064d8422011-07-26 15:38:07 -07003430 if (r.packageName.equals(name)
3431 && (r.app == null || !r.app.persistent)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003432 if (!doit) {
3433 return true;
3434 }
3435 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003436 Slog.i(TAG, " Force finishing activity " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003437 if (r.app != null) {
3438 r.app.removed = true;
3439 }
3440 r.app = null;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003441 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "uninstall");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003442 }
3443 }
3444
3445 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
3446 for (ServiceRecord service : mServices.values()) {
Christopher Tate064d8422011-07-26 15:38:07 -07003447 if (service.packageName.equals(name)
3448 && (service.app == null || !service.app.persistent)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003449 if (!doit) {
3450 return true;
3451 }
3452 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003453 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003454 if (service.app != null) {
3455 service.app.removed = true;
3456 }
3457 service.app = null;
3458 services.add(service);
3459 }
3460 }
3461
3462 N = services.size();
3463 for (i=0; i<N; i++) {
3464 bringDownServiceLocked(services.get(i), true);
3465 }
3466
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003467 if (doit) {
3468 if (purgeCache) {
3469 AttributeCache ac = AttributeCache.instance();
3470 if (ac != null) {
3471 ac.removePackage(name);
3472 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003473 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003474 mMainStack.resumeTopActivityLocked(null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003475 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003476
3477 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003478 }
3479
Dianne Hackborn130b0d22011-07-26 22:07:48 -07003480 private final boolean removeProcessLocked(ProcessRecord app,
3481 boolean callerWillRestart, boolean allowRestart) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003482 final String name = app.processName;
3483 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003484 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003485 TAG, "Force removing process " + app + " (" + name
3486 + "/" + uid + ")");
3487
3488 mProcessNames.remove(name, uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003489 if (mHeavyWeightProcess == app) {
3490 mHeavyWeightProcess = null;
3491 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3492 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003493 boolean needRestart = false;
3494 if (app.pid > 0 && app.pid != MY_PID) {
3495 int pid = app.pid;
3496 synchronized (mPidsSelfLocked) {
3497 mPidsSelfLocked.remove(pid);
3498 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3499 }
Dianne Hackborn130b0d22011-07-26 22:07:48 -07003500 handleAppDiedLocked(app, true, allowRestart);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003501 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003502 Process.killProcess(pid);
3503
3504 if (app.persistent) {
3505 if (!callerWillRestart) {
3506 addAppLocked(app.info);
3507 } else {
3508 needRestart = true;
3509 }
3510 }
3511 } else {
3512 mRemovedProcesses.add(app);
3513 }
3514
3515 return needRestart;
3516 }
3517
3518 private final void processStartTimedOutLocked(ProcessRecord app) {
3519 final int pid = app.pid;
3520 boolean gone = false;
3521 synchronized (mPidsSelfLocked) {
3522 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
3523 if (knownApp != null && knownApp.thread == null) {
3524 mPidsSelfLocked.remove(pid);
3525 gone = true;
3526 }
3527 }
3528
3529 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003530 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003531 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003532 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003533 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003534 if (mHeavyWeightProcess == app) {
3535 mHeavyWeightProcess = null;
3536 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3537 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003538 // Take care of any launching providers waiting for this process.
3539 checkAppInLaunchingProvidersLocked(app, true);
3540 // Take care of any services that are waiting for the process.
3541 for (int i=0; i<mPendingServices.size(); i++) {
3542 ServiceRecord sr = mPendingServices.get(i);
3543 if (app.info.uid == sr.appInfo.uid
3544 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003545 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003546 mPendingServices.remove(i);
3547 i--;
3548 bringDownServiceLocked(sr, true);
3549 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003550 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07003551 EventLog.writeEvent(EventLogTags.AM_KILL, pid,
3552 app.processName, app.setAdj, "start timeout");
3553 Process.killProcessQuiet(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07003554 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003555 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07003556 try {
3557 IBackupManager bm = IBackupManager.Stub.asInterface(
3558 ServiceManager.getService(Context.BACKUP_SERVICE));
3559 bm.agentDisconnected(app.info.packageName);
3560 } catch (RemoteException e) {
3561 // Can't happen; the backup manager is local
3562 }
3563 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003564 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003565 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003566 mPendingBroadcast.state = BroadcastRecord.IDLE;
3567 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003568 mPendingBroadcast = null;
3569 scheduleBroadcastsLocked();
3570 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003571 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003572 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003573 }
3574 }
3575
3576 private final boolean attachApplicationLocked(IApplicationThread thread,
3577 int pid) {
3578
3579 // Find the application record that is being attached... either via
3580 // the pid if we are running in multiple processes, or just pull the
3581 // next app record if we are emulating process with anonymous threads.
3582 ProcessRecord app;
3583 if (pid != MY_PID && pid >= 0) {
3584 synchronized (mPidsSelfLocked) {
3585 app = mPidsSelfLocked.get(pid);
3586 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003587 } else {
3588 app = null;
3589 }
3590
3591 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003592 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003593 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003594 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003595 if (pid > 0 && pid != MY_PID) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07003596 Process.killProcessQuiet(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003597 } else {
3598 try {
3599 thread.scheduleExit();
3600 } catch (Exception e) {
3601 // Ignore exceptions.
3602 }
3603 }
3604 return false;
3605 }
3606
3607 // If this application record is still attached to a previous
3608 // process, clean it up now.
3609 if (app.thread != null) {
Dianne Hackborn130b0d22011-07-26 22:07:48 -07003610 handleAppDiedLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003611 }
3612
3613 // Tell the process all about itself.
3614
Joe Onorato8a9b2202010-02-26 18:56:32 -08003615 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003616 TAG, "Binding process pid " + pid + " to record " + app);
3617
3618 String processName = app.processName;
3619 try {
Dianne Hackborn1b64e0d2011-07-17 15:23:59 -07003620 AppDeathRecipient adr = new AppDeathRecipient(
3621 app, pid, thread);
3622 thread.asBinder().linkToDeath(adr, 0);
3623 app.deathRecipient = adr;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003624 } catch (RemoteException e) {
3625 app.resetPackageList();
3626 startProcessLocked(app, "link fail", processName);
3627 return false;
3628 }
3629
Doug Zongker2bec3d42009-12-04 12:52:44 -08003630 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003631
3632 app.thread = thread;
3633 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08003634 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
3635 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003636 app.forcingToForeground = null;
3637 app.foregroundServices = false;
Dianne Hackbornf0754f5b2011-07-21 16:02:07 -07003638 app.hasShownUi = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003639 app.debugging = false;
3640
3641 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3642
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003643 boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003644 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003645
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003646 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003647 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003648 }
3649
Joe Onorato8a9b2202010-02-26 18:56:32 -08003650 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003651 TAG, "New app record " + app
3652 + " thread=" + thread.asBinder() + " pid=" + pid);
3653 try {
3654 int testMode = IApplicationThread.DEBUG_OFF;
3655 if (mDebugApp != null && mDebugApp.equals(processName)) {
3656 testMode = mWaitForDebugger
3657 ? IApplicationThread.DEBUG_WAIT
3658 : IApplicationThread.DEBUG_ON;
3659 app.debugging = true;
3660 if (mDebugTransient) {
3661 mDebugApp = mOrigDebugApp;
3662 mWaitForDebugger = mOrigWaitForDebugger;
3663 }
3664 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003665
Christopher Tate181fafa2009-05-14 11:12:14 -07003666 // If the app is being launched for restore or full backup, set it up specially
3667 boolean isRestrictedBackupMode = false;
3668 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
3669 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
Christopher Tate75a99702011-05-18 16:28:19 -07003670 || (mBackupTarget.backupMode == BackupRecord.RESTORE_FULL)
Christopher Tate181fafa2009-05-14 11:12:14 -07003671 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
3672 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003673
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07003674 ensurePackageDexOpt(app.instrumentationInfo != null
3675 ? app.instrumentationInfo.packageName
3676 : app.info.packageName);
3677 if (app.instrumentationClass != null) {
3678 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003679 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003680 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003681 + processName + " with config " + mConfiguration);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04003682 ApplicationInfo appInfo = app.instrumentationInfo != null
3683 ? app.instrumentationInfo : app.info;
Dianne Hackborn8ea5e1d2011-05-27 16:45:31 -07003684 app.compat = compatibilityInfoForPackageLocked(appInfo);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04003685 thread.bindApplication(processName, appInfo, providers,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003686 app.instrumentationClass, app.instrumentationProfileFile,
3687 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003688 isRestrictedBackupMode || !normalMode,
Dianne Hackborn8ea5e1d2011-05-27 16:45:31 -07003689 mConfiguration, app.compat, getCommonServicesLocked(),
Svetoslav Ganov54d068e2011-03-02 12:58:40 -08003690 mCoreSettingsObserver.getCoreSettingsLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003691 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003692 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003693 } catch (Exception e) {
3694 // todo: Yikes! What should we do? For now we will try to
3695 // start another process, but that could easily get us in
3696 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08003697 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003698
3699 app.resetPackageList();
Dianne Hackborn1b64e0d2011-07-17 15:23:59 -07003700 app.unlinkDeathRecipient();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003701 startProcessLocked(app, "bind fail", processName);
3702 return false;
3703 }
3704
3705 // Remove this record from the list of starting applications.
3706 mPersistentStartingProcesses.remove(app);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003707 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
3708 "Attach application locked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003709 mProcessesOnHold.remove(app);
3710
3711 boolean badApp = false;
3712 boolean didSomething = false;
3713
3714 // See if the top visible activity is waiting to run in this process...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003715 ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07003716 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003717 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
3718 && processName.equals(hr.processName)) {
3719 try {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003720 if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003721 didSomething = true;
3722 }
3723 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003724 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003725 + hr.intent.getComponent().flattenToShortString(), e);
3726 badApp = true;
3727 }
3728 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003729 mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003730 }
3731 }
3732
3733 // Find any services that should be running in this process...
3734 if (!badApp && mPendingServices.size() > 0) {
3735 ServiceRecord sr = null;
3736 try {
3737 for (int i=0; i<mPendingServices.size(); i++) {
3738 sr = mPendingServices.get(i);
3739 if (app.info.uid != sr.appInfo.uid
3740 || !processName.equals(sr.processName)) {
3741 continue;
3742 }
3743
3744 mPendingServices.remove(i);
3745 i--;
3746 realStartServiceLocked(sr, app);
3747 didSomething = true;
3748 }
3749 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003750 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003751 + sr.shortName, e);
3752 badApp = true;
3753 }
3754 }
3755
3756 // Check if the next broadcast receiver is in this process...
3757 BroadcastRecord br = mPendingBroadcast;
3758 if (!badApp && br != null && br.curApp == app) {
3759 try {
3760 mPendingBroadcast = null;
3761 processCurBroadcastLocked(br, app);
3762 didSomething = true;
3763 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003764 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003765 + br.curComponent.flattenToShortString(), e);
3766 badApp = true;
Jeff Brown4d94a762010-09-23 11:33:28 -07003767 logBroadcastReceiverDiscardLocked(br);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003768 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
3769 br.resultExtras, br.resultAbort, true);
3770 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01003771 // We need to reset the state if we fails to start the receiver.
3772 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003773 }
3774 }
3775
Christopher Tate181fafa2009-05-14 11:12:14 -07003776 // Check whether the next backup agent is in this process...
3777 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003778 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003779 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07003780 try {
Dianne Hackborne2515ee2011-04-27 18:52:56 -04003781 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo,
3782 compatibilityInfoForPackageLocked(mBackupTarget.appInfo),
3783 mBackupTarget.backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -07003784 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003785 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07003786 e.printStackTrace();
3787 }
3788 }
3789
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003790 if (badApp) {
3791 // todo: Also need to kill application to deal with all
3792 // kinds of exceptions.
Dianne Hackborn130b0d22011-07-26 22:07:48 -07003793 handleAppDiedLocked(app, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003794 return false;
3795 }
3796
3797 if (!didSomething) {
3798 updateOomAdjLocked();
3799 }
3800
3801 return true;
3802 }
3803
3804 public final void attachApplication(IApplicationThread thread) {
3805 synchronized (this) {
3806 int callingPid = Binder.getCallingPid();
3807 final long origId = Binder.clearCallingIdentity();
3808 attachApplicationLocked(thread, callingPid);
3809 Binder.restoreCallingIdentity(origId);
3810 }
3811 }
3812
Dianne Hackborne88846e2009-09-30 21:34:25 -07003813 public final void activityIdle(IBinder token, Configuration config) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003814 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003815 mMainStack.activityIdleInternal(token, false, config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003816 Binder.restoreCallingIdentity(origId);
3817 }
3818
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003819 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003820 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003821 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003822 mWindowManager.enableScreenAfterBoot();
3823 }
3824
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003825 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003826 IntentFilter pkgFilter = new IntentFilter();
3827 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
3828 pkgFilter.addDataScheme("package");
3829 mContext.registerReceiver(new BroadcastReceiver() {
3830 @Override
3831 public void onReceive(Context context, Intent intent) {
3832 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
3833 if (pkgs != null) {
3834 for (String pkg : pkgs) {
Vairavan Srinivasan61f07652010-07-22 13:36:40 -07003835 synchronized (ActivityManagerService.this) {
3836 if (forceStopPackageLocked(pkg, -1, false, false, false)) {
3837 setResultCode(Activity.RESULT_OK);
3838 return;
3839 }
3840 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003841 }
3842 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003843 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003844 }, pkgFilter);
3845
3846 synchronized (this) {
3847 // Ensure that any processes we had put on hold are now started
3848 // up.
3849 final int NP = mProcessesOnHold.size();
3850 if (NP > 0) {
3851 ArrayList<ProcessRecord> procs =
3852 new ArrayList<ProcessRecord>(mProcessesOnHold);
3853 for (int ip=0; ip<NP; ip++) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003854 if (DEBUG_PROCESSES) Slog.v(TAG, "Starting process on hold: "
3855 + procs.get(ip));
3856 startProcessLocked(procs.get(ip), "on-hold", null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003857 }
3858 }
3859
3860 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07003861 // Start looking for apps that are abusing wake locks.
3862 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07003863 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003864 // Tell anyone interested that we are done booting!
Dianne Hackbornf4c454b2010-08-11 12:47:41 -07003865 SystemProperties.set("sys.boot_completed", "1");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003866 broadcastIntentLocked(null, null,
3867 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
3868 null, null, 0, null, null,
3869 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
3870 false, false, MY_PID, Process.SYSTEM_UID);
3871 }
3872 }
3873 }
3874
3875 final void ensureBootCompleted() {
3876 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003877 boolean enableScreen;
3878 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003879 booting = mBooting;
3880 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003881 enableScreen = !mBooted;
3882 mBooted = true;
3883 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003884
3885 if (booting) {
3886 finishBooting();
3887 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003888
3889 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003890 enableScreenAfterBoot();
3891 }
3892 }
3893
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08003894 public final void activityPaused(IBinder token) {
3895 final long origId = Binder.clearCallingIdentity();
3896 mMainStack.activityPaused(token, false);
3897 Binder.restoreCallingIdentity(origId);
3898 }
3899
3900 public final void activityStopped(IBinder token, Bundle icicle, Bitmap thumbnail,
3901 CharSequence description) {
3902 if (localLOGV) Slog.v(
3903 TAG, "Activity stopped: token=" + token);
3904
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003905 // Refuse possible leaked file descriptors
3906 if (icicle != null && icicle.hasFileDescriptors()) {
3907 throw new IllegalArgumentException("File descriptors passed in Bundle");
3908 }
3909
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003910 ActivityRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003911
3912 final long origId = Binder.clearCallingIdentity();
3913
3914 synchronized (this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07003915 r = mMainStack.isInStackLocked(token);
3916 if (r != null) {
3917 r.stack.activityStoppedLocked(r, icicle, thumbnail, description);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003918 }
3919 }
3920
3921 if (r != null) {
3922 sendPendingThumbnail(r, null, null, null, false);
3923 }
3924
3925 trimApplications();
3926
3927 Binder.restoreCallingIdentity(origId);
3928 }
3929
3930 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003931 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003932 mMainStack.activityDestroyed(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003933 }
3934
3935 public String getCallingPackage(IBinder token) {
3936 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003937 ActivityRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07003938 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003939 }
3940 }
3941
3942 public ComponentName getCallingActivity(IBinder token) {
3943 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003944 ActivityRecord r = getCallingRecordLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003945 return r != null ? r.intent.getComponent() : null;
3946 }
3947 }
3948
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003949 private ActivityRecord getCallingRecordLocked(IBinder token) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07003950 ActivityRecord r = mMainStack.isInStackLocked(token);
3951 if (r == null) {
3952 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003953 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -07003954 return r.resultTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003955 }
3956
3957 public ComponentName getActivityClassForToken(IBinder token) {
3958 synchronized(this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07003959 ActivityRecord r = mMainStack.isInStackLocked(token);
3960 if (r == null) {
3961 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003962 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -07003963 return r.intent.getComponent();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003964 }
3965 }
3966
3967 public String getPackageForToken(IBinder token) {
3968 synchronized(this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07003969 ActivityRecord r = mMainStack.isInStackLocked(token);
3970 if (r == null) {
3971 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003972 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -07003973 return r.packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003974 }
3975 }
3976
3977 public IIntentSender getIntentSender(int type,
3978 String packageName, IBinder token, String resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003979 int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003980 // Refuse possible leaked file descriptors
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003981 if (intents != null) {
3982 if (intents.length < 1) {
3983 throw new IllegalArgumentException("Intents array length must be >= 1");
3984 }
3985 for (int i=0; i<intents.length; i++) {
3986 Intent intent = intents[i];
Dianne Hackborn52b0ce02011-04-14 13:09:32 -07003987 if (intent != null) {
3988 if (intent.hasFileDescriptors()) {
3989 throw new IllegalArgumentException("File descriptors passed in Intent");
3990 }
3991 if (type == INTENT_SENDER_BROADCAST &&
3992 (intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
3993 throw new IllegalArgumentException(
3994 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
3995 }
3996 intents[i] = new Intent(intent);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003997 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003998 }
3999 if (resolvedTypes != null && resolvedTypes.length != intents.length) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07004000 throw new IllegalArgumentException(
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004001 "Intent array length does not match resolvedTypes length");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07004002 }
4003 }
4004
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004005 synchronized(this) {
4006 int callingUid = Binder.getCallingUid();
4007 try {
Jeff Brown10e89712011-07-08 18:52:57 -07004008 if (callingUid != 0 && callingUid != Process.SYSTEM_UID) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004009 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004010 .getPackageUid(packageName);
4011 if (uid != Binder.getCallingUid()) {
4012 String msg = "Permission Denial: getIntentSender() from pid="
4013 + Binder.getCallingPid()
4014 + ", uid=" + Binder.getCallingUid()
4015 + ", (need uid=" + uid + ")"
4016 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004017 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004018 throw new SecurityException(msg);
4019 }
4020 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004021
4022 return getIntentSenderLocked(type, packageName, callingUid,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004023 token, resultWho, requestCode, intents, resolvedTypes, flags);
Dianne Hackborn860755f2010-06-03 18:47:52 -07004024
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004025 } catch (RemoteException e) {
4026 throw new SecurityException(e);
4027 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004028 }
4029 }
4030
4031 IIntentSender getIntentSenderLocked(int type,
4032 String packageName, int callingUid, IBinder token, String resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004033 int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004034 ActivityRecord activity = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004035 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004036 activity = mMainStack.isInStackLocked(token);
4037 if (activity == null) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07004038 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004039 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004040 if (activity.finishing) {
4041 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004042 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004043 }
4044
4045 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
4046 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
4047 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
4048 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
4049 |PendingIntent.FLAG_UPDATE_CURRENT);
4050
4051 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
4052 type, packageName, activity, resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004053 requestCode, intents, resolvedTypes, flags);
Dianne Hackborn860755f2010-06-03 18:47:52 -07004054 WeakReference<PendingIntentRecord> ref;
4055 ref = mIntentSenderRecords.get(key);
4056 PendingIntentRecord rec = ref != null ? ref.get() : null;
4057 if (rec != null) {
4058 if (!cancelCurrent) {
4059 if (updateCurrent) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004060 if (rec.key.requestIntent != null) {
4061 rec.key.requestIntent.replaceExtras(intents != null ? intents[0] : null);
4062 }
4063 if (intents != null) {
4064 intents[intents.length-1] = rec.key.requestIntent;
4065 rec.key.allIntents = intents;
4066 rec.key.allResolvedTypes = resolvedTypes;
4067 } else {
4068 rec.key.allIntents = null;
4069 rec.key.allResolvedTypes = null;
4070 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004071 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004072 return rec;
4073 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004074 rec.canceled = true;
4075 mIntentSenderRecords.remove(key);
4076 }
4077 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004078 return rec;
4079 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004080 rec = new PendingIntentRecord(this, key, callingUid);
4081 mIntentSenderRecords.put(key, rec.ref);
4082 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
4083 if (activity.pendingResults == null) {
4084 activity.pendingResults
4085 = new HashSet<WeakReference<PendingIntentRecord>>();
4086 }
4087 activity.pendingResults.add(rec.ref);
4088 }
4089 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004090 }
4091
4092 public void cancelIntentSender(IIntentSender sender) {
4093 if (!(sender instanceof PendingIntentRecord)) {
4094 return;
4095 }
4096 synchronized(this) {
4097 PendingIntentRecord rec = (PendingIntentRecord)sender;
4098 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004099 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004100 .getPackageUid(rec.key.packageName);
4101 if (uid != Binder.getCallingUid()) {
4102 String msg = "Permission Denial: cancelIntentSender() from pid="
4103 + Binder.getCallingPid()
4104 + ", uid=" + Binder.getCallingUid()
4105 + " is not allowed to cancel packges "
4106 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004107 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004108 throw new SecurityException(msg);
4109 }
4110 } catch (RemoteException e) {
4111 throw new SecurityException(e);
4112 }
4113 cancelIntentSenderLocked(rec, true);
4114 }
4115 }
4116
4117 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
4118 rec.canceled = true;
4119 mIntentSenderRecords.remove(rec.key);
4120 if (cleanActivity && rec.key.activity != null) {
4121 rec.key.activity.pendingResults.remove(rec.ref);
4122 }
4123 }
4124
4125 public String getPackageForIntentSender(IIntentSender pendingResult) {
4126 if (!(pendingResult instanceof PendingIntentRecord)) {
4127 return null;
4128 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07004129 try {
4130 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
4131 return res.key.packageName;
4132 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004133 }
4134 return null;
4135 }
4136
Dianne Hackborn6c418d52011-06-29 14:05:33 -07004137 public boolean isIntentSenderTargetedToPackage(IIntentSender pendingResult) {
4138 if (!(pendingResult instanceof PendingIntentRecord)) {
4139 return false;
4140 }
4141 try {
4142 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
4143 if (res.key.allIntents == null) {
4144 return false;
4145 }
4146 for (int i=0; i<res.key.allIntents.length; i++) {
4147 Intent intent = res.key.allIntents[i];
4148 if (intent.getPackage() != null && intent.getComponent() != null) {
4149 return false;
4150 }
4151 }
4152 return true;
4153 } catch (ClassCastException e) {
4154 }
4155 return false;
4156 }
4157
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004158 public void setProcessLimit(int max) {
4159 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4160 "setProcessLimit()");
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004161 synchronized (this) {
4162 mProcessLimit = max < 0 ? MAX_HIDDEN_APPS : max;
4163 mProcessLimitOverride = max;
4164 }
4165 trimApplications();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004166 }
4167
4168 public int getProcessLimit() {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004169 synchronized (this) {
4170 return mProcessLimitOverride;
4171 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004172 }
4173
4174 void foregroundTokenDied(ForegroundToken token) {
4175 synchronized (ActivityManagerService.this) {
4176 synchronized (mPidsSelfLocked) {
4177 ForegroundToken cur
4178 = mForegroundProcesses.get(token.pid);
4179 if (cur != token) {
4180 return;
4181 }
4182 mForegroundProcesses.remove(token.pid);
4183 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
4184 if (pr == null) {
4185 return;
4186 }
4187 pr.forcingToForeground = null;
4188 pr.foregroundServices = false;
4189 }
4190 updateOomAdjLocked();
4191 }
4192 }
4193
4194 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
4195 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4196 "setProcessForeground()");
4197 synchronized(this) {
4198 boolean changed = false;
4199
4200 synchronized (mPidsSelfLocked) {
4201 ProcessRecord pr = mPidsSelfLocked.get(pid);
4202 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004203 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004204 return;
4205 }
4206 ForegroundToken oldToken = mForegroundProcesses.get(pid);
4207 if (oldToken != null) {
4208 oldToken.token.unlinkToDeath(oldToken, 0);
4209 mForegroundProcesses.remove(pid);
4210 pr.forcingToForeground = null;
4211 changed = true;
4212 }
4213 if (isForeground && token != null) {
4214 ForegroundToken newToken = new ForegroundToken() {
4215 public void binderDied() {
4216 foregroundTokenDied(this);
4217 }
4218 };
4219 newToken.pid = pid;
4220 newToken.token = token;
4221 try {
4222 token.linkToDeath(newToken, 0);
4223 mForegroundProcesses.put(pid, newToken);
4224 pr.forcingToForeground = token;
4225 changed = true;
4226 } catch (RemoteException e) {
4227 // If the process died while doing this, we will later
4228 // do the cleanup with the process death link.
4229 }
4230 }
4231 }
4232
4233 if (changed) {
4234 updateOomAdjLocked();
4235 }
4236 }
4237 }
4238
4239 // =========================================================
4240 // PERMISSIONS
4241 // =========================================================
4242
4243 static class PermissionController extends IPermissionController.Stub {
4244 ActivityManagerService mActivityManagerService;
4245 PermissionController(ActivityManagerService activityManagerService) {
4246 mActivityManagerService = activityManagerService;
4247 }
4248
4249 public boolean checkPermission(String permission, int pid, int uid) {
4250 return mActivityManagerService.checkPermission(permission, pid,
4251 uid) == PackageManager.PERMISSION_GRANTED;
4252 }
4253 }
4254
4255 /**
4256 * This can be called with or without the global lock held.
4257 */
4258 int checkComponentPermission(String permission, int pid, int uid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004259 int owningUid, boolean exported) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004260 // We might be performing an operation on behalf of an indirect binder
4261 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
4262 // client identity accordingly before proceeding.
4263 Identity tlsIdentity = sCallerIdentity.get();
4264 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004265 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004266 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
4267 uid = tlsIdentity.uid;
4268 pid = tlsIdentity.pid;
4269 }
4270
4271 // Root, system server and our own process get to do everything.
Jeff Brown10e89712011-07-08 18:52:57 -07004272 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004273 return PackageManager.PERMISSION_GRANTED;
4274 }
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004275 // If there is a uid that owns whatever is being accessed, it has
4276 // blanket access to it regardless of the permissions it requires.
4277 if (owningUid >= 0 && uid == owningUid) {
4278 return PackageManager.PERMISSION_GRANTED;
4279 }
4280 // If the target is not exported, then nobody else can get to it.
4281 if (!exported) {
4282 Slog.w(TAG, "Permission denied: checkComponentPermission() owningUid=" + owningUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004283 return PackageManager.PERMISSION_DENIED;
4284 }
4285 if (permission == null) {
4286 return PackageManager.PERMISSION_GRANTED;
4287 }
4288 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004289 return AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004290 .checkUidPermission(permission, uid);
4291 } catch (RemoteException e) {
4292 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004293 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004294 }
4295 return PackageManager.PERMISSION_DENIED;
4296 }
4297
4298 /**
4299 * As the only public entry point for permissions checking, this method
4300 * can enforce the semantic that requesting a check on a null global
4301 * permission is automatically denied. (Internally a null permission
4302 * string is used when calling {@link #checkComponentPermission} in cases
4303 * when only uid-based security is needed.)
4304 *
4305 * This can be called with or without the global lock held.
4306 */
4307 public int checkPermission(String permission, int pid, int uid) {
4308 if (permission == null) {
4309 return PackageManager.PERMISSION_DENIED;
4310 }
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004311 return checkComponentPermission(permission, pid, uid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004312 }
4313
4314 /**
4315 * Binder IPC calls go through the public entry point.
4316 * This can be called with or without the global lock held.
4317 */
4318 int checkCallingPermission(String permission) {
4319 return checkPermission(permission,
4320 Binder.getCallingPid(),
4321 Binder.getCallingUid());
4322 }
4323
4324 /**
4325 * This can be called with or without the global lock held.
4326 */
4327 void enforceCallingPermission(String permission, String func) {
4328 if (checkCallingPermission(permission)
4329 == PackageManager.PERMISSION_GRANTED) {
4330 return;
4331 }
4332
4333 String msg = "Permission Denial: " + func + " from pid="
4334 + Binder.getCallingPid()
4335 + ", uid=" + Binder.getCallingUid()
4336 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004337 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004338 throw new SecurityException(msg);
4339 }
4340
4341 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
Dianne Hackborn48058e82010-09-27 16:53:23 -07004342 ProviderInfo pi, Uri uri, int uid, int modeFlags) {
4343 boolean readPerm = (modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0;
4344 boolean writePerm = (modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0;
4345 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4346 "checkHoldingPermissionsLocked: uri=" + uri + " uid=" + uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004347 try {
Dianne Hackborn48058e82010-09-27 16:53:23 -07004348 // Is the component private from the target uid?
4349 final boolean prv = !pi.exported && pi.applicationInfo.uid != uid;
4350
4351 // Acceptable if the there is no read permission needed from the
4352 // target or the target is holding the read permission.
4353 if (!readPerm) {
4354 if ((!prv && pi.readPermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004355 (pm.checkUidPermission(pi.readPermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004356 == PackageManager.PERMISSION_GRANTED)) {
4357 readPerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004358 }
4359 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004360
4361 // Acceptable if the there is no write permission needed from the
4362 // target or the target is holding the read permission.
4363 if (!writePerm) {
4364 if (!prv && (pi.writePermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004365 (pm.checkUidPermission(pi.writePermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004366 == PackageManager.PERMISSION_GRANTED)) {
4367 writePerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004368 }
4369 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004370
4371 // Acceptable if there is a path permission matching the URI that
4372 // the target holds the permission on.
4373 PathPermission[] pps = pi.pathPermissions;
4374 if (pps != null && (!readPerm || !writePerm)) {
4375 final String path = uri.getPath();
4376 int i = pps.length;
4377 while (i > 0 && (!readPerm || !writePerm)) {
4378 i--;
4379 PathPermission pp = pps[i];
4380 if (!readPerm) {
4381 final String pprperm = pp.getReadPermission();
4382 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking read perm for "
4383 + pprperm + " for " + pp.getPath()
4384 + ": match=" + pp.match(path)
4385 + " check=" + pm.checkUidPermission(pprperm, uid));
4386 if (pprperm != null && pp.match(path) &&
4387 (pm.checkUidPermission(pprperm, uid)
4388 == PackageManager.PERMISSION_GRANTED)) {
4389 readPerm = true;
4390 }
4391 }
4392 if (!writePerm) {
4393 final String ppwperm = pp.getWritePermission();
4394 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking write perm "
4395 + ppwperm + " for " + pp.getPath()
4396 + ": match=" + pp.match(path)
4397 + " check=" + pm.checkUidPermission(ppwperm, uid));
4398 if (ppwperm != null && pp.match(path) &&
4399 (pm.checkUidPermission(ppwperm, uid)
4400 == PackageManager.PERMISSION_GRANTED)) {
4401 writePerm = true;
4402 }
4403 }
4404 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004405 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004406 } catch (RemoteException e) {
4407 return false;
4408 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004409
4410 return readPerm && writePerm;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004411 }
4412
4413 private final boolean checkUriPermissionLocked(Uri uri, int uid,
4414 int modeFlags) {
4415 // Root gets to do everything.
Jeff Brown10e89712011-07-08 18:52:57 -07004416 if (uid == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004417 return true;
4418 }
4419 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
4420 if (perms == null) return false;
4421 UriPermission perm = perms.get(uri);
4422 if (perm == null) return false;
4423 return (modeFlags&perm.modeFlags) == modeFlags;
4424 }
4425
4426 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
4427 // Another redirected-binder-call permissions check as in
4428 // {@link checkComponentPermission}.
4429 Identity tlsIdentity = sCallerIdentity.get();
4430 if (tlsIdentity != null) {
4431 uid = tlsIdentity.uid;
4432 pid = tlsIdentity.pid;
4433 }
4434
4435 // Our own process gets to do everything.
4436 if (pid == MY_PID) {
4437 return PackageManager.PERMISSION_GRANTED;
4438 }
4439 synchronized(this) {
4440 return checkUriPermissionLocked(uri, uid, modeFlags)
4441 ? PackageManager.PERMISSION_GRANTED
4442 : PackageManager.PERMISSION_DENIED;
4443 }
4444 }
4445
Dianne Hackborn39792d22010-08-19 18:01:52 -07004446 /**
4447 * Check if the targetPkg can be granted permission to access uri by
4448 * the callingUid using the given modeFlags. Throws a security exception
4449 * if callingUid is not allowed to do this. Returns the uid of the target
4450 * if the URI permission grant should be performed; returns -1 if it is not
4451 * needed (for example targetPkg already has permission to access the URI).
4452 */
4453 int checkGrantUriPermissionLocked(int callingUid, String targetPkg,
4454 Uri uri, int modeFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004455 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4456 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4457 if (modeFlags == 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004458 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004459 }
4460
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004461 if (targetPkg != null) {
4462 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4463 "Checking grant " + targetPkg + " permission to " + uri);
4464 }
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004465
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004466 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004467
4468 // If this is not a content: uri, we can't do anything with it.
4469 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004470 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004471 "Can't grant URI permission for non-content URI: " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004472 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004473 }
4474
4475 String name = uri.getAuthority();
4476 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004477 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004478 if (cpr != null) {
4479 pi = cpr.info;
4480 } else {
4481 try {
4482 pi = pm.resolveContentProvider(name,
4483 PackageManager.GET_URI_PERMISSION_PATTERNS);
4484 } catch (RemoteException ex) {
4485 }
4486 }
4487 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004488 Slog.w(TAG, "No content provider found for: " + name);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004489 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004490 }
4491
4492 int targetUid;
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004493 if (targetPkg != null) {
4494 try {
4495 targetUid = pm.getPackageUid(targetPkg);
4496 if (targetUid < 0) {
4497 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4498 "Can't grant URI permission no uid for: " + targetPkg);
4499 return -1;
4500 }
4501 } catch (RemoteException ex) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004502 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004503 }
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004504 } else {
4505 targetUid = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004506 }
4507
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004508 if (targetUid >= 0) {
4509 // First... does the target actually need this permission?
4510 if (checkHoldingPermissionsLocked(pm, pi, uri, targetUid, modeFlags)) {
4511 // No need to grant the target this permission.
4512 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4513 "Target " + targetPkg + " already has full permission to " + uri);
4514 return -1;
4515 }
4516 } else {
4517 // First... there is no target package, so can anyone access it?
4518 boolean allowed = pi.exported;
4519 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4520 if (pi.readPermission != null) {
4521 allowed = false;
4522 }
4523 }
4524 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4525 if (pi.writePermission != null) {
4526 allowed = false;
4527 }
4528 }
4529 if (allowed) {
4530 return -1;
4531 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004532 }
4533
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004534 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004535 if (!pi.grantUriPermissions) {
4536 throw new SecurityException("Provider " + pi.packageName
4537 + "/" + pi.name
4538 + " does not allow granting of Uri permissions (uri "
4539 + uri + ")");
4540 }
4541 if (pi.uriPermissionPatterns != null) {
4542 final int N = pi.uriPermissionPatterns.length;
4543 boolean allowed = false;
4544 for (int i=0; i<N; i++) {
4545 if (pi.uriPermissionPatterns[i] != null
4546 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
4547 allowed = true;
4548 break;
4549 }
4550 }
4551 if (!allowed) {
4552 throw new SecurityException("Provider " + pi.packageName
4553 + "/" + pi.name
4554 + " does not allow granting of permission to path of Uri "
4555 + uri);
4556 }
4557 }
4558
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004559 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004560 // this uri?
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004561 if (callingUid != Process.myUid()) {
4562 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
4563 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4564 throw new SecurityException("Uid " + callingUid
4565 + " does not have permission to uri " + uri);
4566 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004567 }
4568 }
4569
Dianne Hackborn39792d22010-08-19 18:01:52 -07004570 return targetUid;
4571 }
4572
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004573 public int checkGrantUriPermission(int callingUid, String targetPkg,
4574 Uri uri, int modeFlags) {
4575 synchronized(this) {
4576 return checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4577 }
4578 }
4579
Dianne Hackborn39792d22010-08-19 18:01:52 -07004580 void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg,
4581 Uri uri, int modeFlags, UriPermissionOwner owner) {
4582 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4583 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4584 if (modeFlags == 0) {
4585 return;
4586 }
4587
4588 // So here we are: the caller has the assumed permission
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004589 // to the uri, and the target doesn't. Let's now give this to
4590 // the target.
4591
Joe Onorato8a9b2202010-02-26 18:56:32 -08004592 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004593 "Granting " + targetPkg + "/" + targetUid + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004594
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004595 HashMap<Uri, UriPermission> targetUris
4596 = mGrantedUriPermissions.get(targetUid);
4597 if (targetUris == null) {
4598 targetUris = new HashMap<Uri, UriPermission>();
4599 mGrantedUriPermissions.put(targetUid, targetUris);
4600 }
4601
4602 UriPermission perm = targetUris.get(uri);
4603 if (perm == null) {
4604 perm = new UriPermission(targetUid, uri);
4605 targetUris.put(uri, perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004606 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004607
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004608 perm.modeFlags |= modeFlags;
Dianne Hackborn39792d22010-08-19 18:01:52 -07004609 if (owner == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004610 perm.globalModeFlags |= modeFlags;
Vairavan Srinivasan91c12c22011-01-21 18:26:06 -08004611 } else {
4612 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4613 perm.readOwners.add(owner);
4614 owner.addReadPermission(perm);
4615 }
4616 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4617 perm.writeOwners.add(owner);
4618 owner.addWritePermission(perm);
4619 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004620 }
4621 }
4622
Dianne Hackborn39792d22010-08-19 18:01:52 -07004623 void grantUriPermissionLocked(int callingUid,
4624 String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) {
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004625 if (targetPkg == null) {
4626 throw new NullPointerException("targetPkg");
4627 }
4628
Dianne Hackborn39792d22010-08-19 18:01:52 -07004629 int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4630 if (targetUid < 0) {
4631 return;
4632 }
4633
4634 grantUriPermissionUncheckedLocked(targetUid, targetPkg, uri, modeFlags, owner);
4635 }
4636
4637 /**
4638 * Like checkGrantUriPermissionLocked, but takes an Intent.
4639 */
4640 int checkGrantUriPermissionFromIntentLocked(int callingUid,
4641 String targetPkg, Intent intent) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07004642 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004643 "Checking URI perm to " + (intent != null ? intent.getData() : null)
Dianne Hackbornb424b632010-08-18 15:59:05 -07004644 + " from " + intent + "; flags=0x"
4645 + Integer.toHexString(intent != null ? intent.getFlags() : 0));
4646
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004647 if (targetPkg == null) {
4648 throw new NullPointerException("targetPkg");
4649 }
4650
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004651 if (intent == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004652 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004653 }
4654 Uri data = intent.getData();
4655 if (data == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004656 return -1;
4657 }
4658 return checkGrantUriPermissionLocked(callingUid, targetPkg, data,
4659 intent.getFlags());
4660 }
4661
4662 /**
4663 * Like grantUriPermissionUncheckedLocked, but takes an Intent.
4664 */
4665 void grantUriPermissionUncheckedFromIntentLocked(int targetUid,
4666 String targetPkg, Intent intent, UriPermissionOwner owner) {
4667 grantUriPermissionUncheckedLocked(targetUid, targetPkg, intent.getData(),
4668 intent.getFlags(), owner);
4669 }
4670
4671 void grantUriPermissionFromIntentLocked(int callingUid,
4672 String targetPkg, Intent intent, UriPermissionOwner owner) {
4673 int targetUid = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg, intent);
4674 if (targetUid < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004675 return;
4676 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07004677
4678 grantUriPermissionUncheckedFromIntentLocked(targetUid, targetPkg, intent, owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004679 }
4680
4681 public void grantUriPermission(IApplicationThread caller, String targetPkg,
4682 Uri uri, int modeFlags) {
4683 synchronized(this) {
4684 final ProcessRecord r = getRecordForAppLocked(caller);
4685 if (r == null) {
4686 throw new SecurityException("Unable to find app for caller "
4687 + caller
4688 + " when granting permission to uri " + uri);
4689 }
4690 if (targetPkg == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004691 throw new IllegalArgumentException("null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004692 }
4693 if (uri == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004694 throw new IllegalArgumentException("null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004695 }
4696
4697 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
4698 null);
4699 }
4700 }
4701
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004702 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004703 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
4704 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
4705 HashMap<Uri, UriPermission> perms
4706 = mGrantedUriPermissions.get(perm.uid);
4707 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004708 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004709 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004710 perms.remove(perm.uri);
4711 if (perms.size() == 0) {
4712 mGrantedUriPermissions.remove(perm.uid);
4713 }
4714 }
4715 }
4716 }
4717
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004718 private void revokeUriPermissionLocked(int callingUid, Uri uri,
4719 int modeFlags) {
4720 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4721 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4722 if (modeFlags == 0) {
4723 return;
4724 }
4725
Joe Onorato8a9b2202010-02-26 18:56:32 -08004726 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004727 "Revoking all granted permissions to " + uri);
4728
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004729 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004730
4731 final String authority = uri.getAuthority();
4732 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004733 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004734 if (cpr != null) {
4735 pi = cpr.info;
4736 } else {
4737 try {
4738 pi = pm.resolveContentProvider(authority,
4739 PackageManager.GET_URI_PERMISSION_PATTERNS);
4740 } catch (RemoteException ex) {
4741 }
4742 }
4743 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004744 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004745 return;
4746 }
4747
4748 // Does the caller have this permission on the URI?
Dianne Hackborn48058e82010-09-27 16:53:23 -07004749 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004750 // Right now, if you are not the original owner of the permission,
4751 // you are not allowed to revoke it.
4752 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4753 throw new SecurityException("Uid " + callingUid
4754 + " does not have permission to uri " + uri);
4755 //}
4756 }
4757
4758 // Go through all of the permissions and remove any that match.
4759 final List<String> SEGMENTS = uri.getPathSegments();
4760 if (SEGMENTS != null) {
4761 final int NS = SEGMENTS.size();
4762 int N = mGrantedUriPermissions.size();
4763 for (int i=0; i<N; i++) {
4764 HashMap<Uri, UriPermission> perms
4765 = mGrantedUriPermissions.valueAt(i);
4766 Iterator<UriPermission> it = perms.values().iterator();
4767 toploop:
4768 while (it.hasNext()) {
4769 UriPermission perm = it.next();
4770 Uri targetUri = perm.uri;
4771 if (!authority.equals(targetUri.getAuthority())) {
4772 continue;
4773 }
4774 List<String> targetSegments = targetUri.getPathSegments();
4775 if (targetSegments == null) {
4776 continue;
4777 }
4778 if (targetSegments.size() < NS) {
4779 continue;
4780 }
4781 for (int j=0; j<NS; j++) {
4782 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
4783 continue toploop;
4784 }
4785 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004786 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004787 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004788 perm.clearModes(modeFlags);
4789 if (perm.modeFlags == 0) {
4790 it.remove();
4791 }
4792 }
4793 if (perms.size() == 0) {
4794 mGrantedUriPermissions.remove(
4795 mGrantedUriPermissions.keyAt(i));
4796 N--;
4797 i--;
4798 }
4799 }
4800 }
4801 }
4802
4803 public void revokeUriPermission(IApplicationThread caller, Uri uri,
4804 int modeFlags) {
4805 synchronized(this) {
4806 final ProcessRecord r = getRecordForAppLocked(caller);
4807 if (r == null) {
4808 throw new SecurityException("Unable to find app for caller "
4809 + caller
4810 + " when revoking permission to uri " + uri);
4811 }
4812 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004813 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004814 return;
4815 }
4816
4817 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4818 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4819 if (modeFlags == 0) {
4820 return;
4821 }
4822
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004823 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004824
4825 final String authority = uri.getAuthority();
4826 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004827 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004828 if (cpr != null) {
4829 pi = cpr.info;
4830 } else {
4831 try {
4832 pi = pm.resolveContentProvider(authority,
4833 PackageManager.GET_URI_PERMISSION_PATTERNS);
4834 } catch (RemoteException ex) {
4835 }
4836 }
4837 if (pi == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004838 Slog.w(TAG, "No content provider found for: " + authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004839 return;
4840 }
4841
4842 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
4843 }
4844 }
4845
Dianne Hackborn7e269642010-08-25 19:50:20 -07004846 @Override
4847 public IBinder newUriPermissionOwner(String name) {
4848 synchronized(this) {
4849 UriPermissionOwner owner = new UriPermissionOwner(this, name);
4850 return owner.getExternalTokenLocked();
4851 }
4852 }
4853
4854 @Override
4855 public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg,
4856 Uri uri, int modeFlags) {
4857 synchronized(this) {
4858 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4859 if (owner == null) {
4860 throw new IllegalArgumentException("Unknown owner: " + token);
4861 }
4862 if (fromUid != Binder.getCallingUid()) {
4863 if (Binder.getCallingUid() != Process.myUid()) {
4864 // Only system code can grant URI permissions on behalf
4865 // of other users.
4866 throw new SecurityException("nice try");
4867 }
4868 }
4869 if (targetPkg == null) {
4870 throw new IllegalArgumentException("null target");
4871 }
4872 if (uri == null) {
4873 throw new IllegalArgumentException("null uri");
4874 }
4875
4876 grantUriPermissionLocked(fromUid, targetPkg, uri, modeFlags, owner);
4877 }
4878 }
4879
4880 @Override
4881 public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode) {
4882 synchronized(this) {
4883 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4884 if (owner == null) {
4885 throw new IllegalArgumentException("Unknown owner: " + token);
4886 }
4887
4888 if (uri == null) {
4889 owner.removeUriPermissionsLocked(mode);
4890 } else {
4891 owner.removeUriPermissionLocked(uri, mode);
4892 }
4893 }
4894 }
4895
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004896 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
4897 synchronized (this) {
4898 ProcessRecord app =
4899 who != null ? getRecordForAppLocked(who) : null;
4900 if (app == null) return;
4901
4902 Message msg = Message.obtain();
4903 msg.what = WAIT_FOR_DEBUGGER_MSG;
4904 msg.obj = app;
4905 msg.arg1 = waiting ? 1 : 0;
4906 mHandler.sendMessage(msg);
4907 }
4908 }
4909
4910 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
4911 outInfo.availMem = Process.getFreeMemory();
The Android Open Source Project4df24232009-03-05 14:34:35 -08004912 outInfo.threshold = HOME_APP_MEM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004913 outInfo.lowMemory = outInfo.availMem <
The Android Open Source Project4df24232009-03-05 14:34:35 -08004914 (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004915 }
4916
4917 // =========================================================
4918 // TASK MANAGEMENT
4919 // =========================================================
4920
4921 public List getTasks(int maxNum, int flags,
4922 IThumbnailReceiver receiver) {
4923 ArrayList list = new ArrayList();
4924
4925 PendingThumbnailsRecord pending = null;
4926 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004927 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004928
4929 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004930 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004931 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
4932 + ", receiver=" + receiver);
4933
4934 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
4935 != PackageManager.PERMISSION_GRANTED) {
4936 if (receiver != null) {
4937 // If the caller wants to wait for pending thumbnails,
4938 // it ain't gonna get them.
4939 try {
4940 receiver.finished();
4941 } catch (RemoteException ex) {
4942 }
4943 }
4944 String msg = "Permission Denial: getTasks() from pid="
4945 + Binder.getCallingPid()
4946 + ", uid=" + Binder.getCallingUid()
4947 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004948 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004949 throw new SecurityException(msg);
4950 }
4951
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004952 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004953 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004954 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004955 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004956 TaskRecord curTask = null;
4957 int numActivities = 0;
4958 int numRunning = 0;
4959 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004960 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004961 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004962 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004963
4964 // Initialize state for next task if needed.
4965 if (top == null ||
4966 (top.state == ActivityState.INITIALIZING
4967 && top.task == r.task)) {
4968 top = r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004969 curTask = r.task;
4970 numActivities = numRunning = 0;
4971 }
4972
4973 // Add 'r' into the current task.
4974 numActivities++;
4975 if (r.app != null && r.app.thread != null) {
4976 numRunning++;
4977 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004978
Joe Onorato8a9b2202010-02-26 18:56:32 -08004979 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004980 TAG, r.intent.getComponent().flattenToShortString()
4981 + ": task=" + r.task);
4982
4983 // If the next one is a different task, generate a new
4984 // TaskInfo entry for what we have.
4985 if (next == null || next.task != curTask) {
4986 ActivityManager.RunningTaskInfo ci
4987 = new ActivityManager.RunningTaskInfo();
4988 ci.id = curTask.taskId;
4989 ci.baseActivity = r.intent.getComponent();
4990 ci.topActivity = top.intent.getComponent();
Dianne Hackbornf26fd992011-04-08 18:14:09 -07004991 if (top.thumbHolder != null) {
4992 ci.description = top.thumbHolder.lastDescription;
4993 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004994 ci.numActivities = numActivities;
4995 ci.numRunning = numRunning;
4996 //System.out.println(
4997 // "#" + maxNum + ": " + " descr=" + ci.description);
4998 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004999 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005000 TAG, "State=" + top.state + "Idle=" + top.idle
5001 + " app=" + top.app
5002 + " thr=" + (top.app != null ? top.app.thread : null));
5003 if (top.state == ActivityState.RESUMED
5004 || top.state == ActivityState.PAUSING) {
5005 if (top.idle && top.app != null
5006 && top.app.thread != null) {
5007 topRecord = top;
5008 topThumbnail = top.app.thread;
5009 } else {
5010 top.thumbnailNeeded = true;
5011 }
5012 }
5013 if (pending == null) {
5014 pending = new PendingThumbnailsRecord(receiver);
5015 }
5016 pending.pendingRecords.add(top);
5017 }
5018 list.add(ci);
5019 maxNum--;
5020 top = null;
5021 }
5022 }
5023
5024 if (pending != null) {
5025 mPendingThumbnails.add(pending);
5026 }
5027 }
5028
Joe Onorato8a9b2202010-02-26 18:56:32 -08005029 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005030
5031 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005032 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005033 try {
5034 topThumbnail.requestThumbnail(topRecord);
5035 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005036 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005037 sendPendingThumbnail(null, topRecord, null, null, true);
5038 }
5039 }
5040
5041 if (pending == null && receiver != null) {
5042 // In this case all thumbnails were available and the client
5043 // is being asked to be told when the remaining ones come in...
5044 // which is unusually, since the top-most currently running
5045 // activity should never have a canned thumbnail! Oh well.
5046 try {
5047 receiver.finished();
5048 } catch (RemoteException ex) {
5049 }
5050 }
5051
5052 return list;
5053 }
5054
5055 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
5056 int flags) {
5057 synchronized (this) {
5058 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
5059 "getRecentTasks()");
5060
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005061 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07005062
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005063 final int N = mRecentTasks.size();
5064 ArrayList<ActivityManager.RecentTaskInfo> res
5065 = new ArrayList<ActivityManager.RecentTaskInfo>(
5066 maxNum < N ? maxNum : N);
5067 for (int i=0; i<N && maxNum > 0; i++) {
5068 TaskRecord tr = mRecentTasks.get(i);
5069 if (((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
5070 || (tr.intent == null)
5071 || ((tr.intent.getFlags()
5072 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
5073 ActivityManager.RecentTaskInfo rti
5074 = new ActivityManager.RecentTaskInfo();
5075 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
Dianne Hackbornd94df452011-02-16 18:53:31 -08005076 rti.persistentId = tr.taskId;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005077 rti.baseIntent = new Intent(
5078 tr.intent != null ? tr.intent : tr.affinityIntent);
5079 rti.origActivity = tr.origActivity;
Dianne Hackbornd2835932010-12-13 16:28:46 -08005080 rti.description = tr.lastDescription;
5081
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07005082 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
5083 // Check whether this activity is currently available.
5084 try {
5085 if (rti.origActivity != null) {
5086 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
5087 continue;
5088 }
5089 } else if (rti.baseIntent != null) {
5090 if (pm.queryIntentActivities(rti.baseIntent,
5091 null, 0) == null) {
5092 continue;
5093 }
5094 }
5095 } catch (RemoteException e) {
5096 // Will never happen.
5097 }
5098 }
5099
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005100 res.add(rti);
5101 maxNum--;
5102 }
5103 }
5104 return res;
5105 }
5106 }
5107
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005108 private TaskRecord taskForIdLocked(int id) {
5109 final int N = mRecentTasks.size();
5110 for (int i=0; i<N; i++) {
5111 TaskRecord tr = mRecentTasks.get(i);
5112 if (tr.taskId == id) {
5113 return tr;
Dianne Hackbornd94df452011-02-16 18:53:31 -08005114 }
5115 }
5116 return null;
5117 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005118
5119 public ActivityManager.TaskThumbnails getTaskThumbnails(int id) {
5120 synchronized (this) {
5121 enforceCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER,
5122 "getTaskThumbnails()");
5123 TaskRecord tr = taskForIdLocked(id);
5124 if (tr != null) {
5125 return mMainStack.getTaskThumbnailsLocked(tr);
5126 }
5127 }
5128 return null;
5129 }
5130
5131 public boolean removeSubTask(int taskId, int subTaskIndex) {
5132 synchronized (this) {
5133 enforceCallingPermission(android.Manifest.permission.REMOVE_TASKS,
5134 "removeSubTask()");
5135 long ident = Binder.clearCallingIdentity();
5136 try {
5137 return mMainStack.removeTaskActivitiesLocked(taskId, subTaskIndex) != null;
5138 } finally {
5139 Binder.restoreCallingIdentity(ident);
5140 }
5141 }
5142 }
5143
Dianne Hackborn8894cc52011-07-01 16:28:17 -07005144 private void cleanUpRemovedTaskLocked(ActivityRecord root, boolean killProcesses) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005145 TaskRecord tr = root.task;
5146 Intent baseIntent = new Intent(
5147 tr.intent != null ? tr.intent : tr.affinityIntent);
5148 ComponentName component = baseIntent.getComponent();
5149 if (component == null) {
5150 Slog.w(TAG, "Now component for base intent of task: " + tr);
5151 return;
5152 }
5153
5154 // Find any running services associated with this app.
5155 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
5156 for (ServiceRecord sr : mServices.values()) {
5157 if (sr.packageName.equals(component.getPackageName())) {
5158 services.add(sr);
5159 }
5160 }
5161
5162 // Take care of any running services associated with the app.
5163 for (int i=0; i<services.size(); i++) {
5164 ServiceRecord sr = services.get(i);
5165 if (sr.startRequested) {
5166 if ((sr.serviceInfo.flags&ServiceInfo.FLAG_STOP_WITH_TASK) != 0) {
Dianne Hackborn8894cc52011-07-01 16:28:17 -07005167 Slog.i(TAG, "Stopping service " + sr.shortName + ": remove task");
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005168 stopServiceLocked(sr);
5169 } else {
5170 sr.pendingStarts.add(new ServiceRecord.StartItem(sr, true,
5171 sr.makeNextStartId(), baseIntent, -1));
5172 if (sr.app != null && sr.app.thread != null) {
5173 sendServiceArgsLocked(sr, false);
5174 }
5175 }
5176 }
5177 }
5178
Dianne Hackborn8894cc52011-07-01 16:28:17 -07005179 if (killProcesses) {
5180 // Find any running processes associated with this app.
5181 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
5182 SparseArray<ProcessRecord> appProcs
5183 = mProcessNames.getMap().get(component.getPackageName());
5184 if (appProcs != null) {
5185 for (int i=0; i<appProcs.size(); i++) {
5186 procs.add(appProcs.valueAt(i));
5187 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005188 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005189
Dianne Hackborn8894cc52011-07-01 16:28:17 -07005190 // Kill the running processes.
5191 for (int i=0; i<procs.size(); i++) {
5192 ProcessRecord pr = procs.get(i);
5193 if (pr.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {
5194 Slog.i(TAG, "Killing " + pr.toShortString() + ": remove task");
5195 EventLog.writeEvent(EventLogTags.AM_KILL, pr.pid,
5196 pr.processName, pr.setAdj, "remove task");
5197 Process.killProcessQuiet(pr.pid);
5198 } else {
5199 pr.waitingToKill = "remove task";
5200 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005201 }
5202 }
5203 }
5204
5205 public boolean removeTask(int taskId, int flags) {
5206 synchronized (this) {
5207 enforceCallingPermission(android.Manifest.permission.REMOVE_TASKS,
5208 "removeTask()");
5209 long ident = Binder.clearCallingIdentity();
5210 try {
5211 ActivityRecord r = mMainStack.removeTaskActivitiesLocked(taskId, -1);
5212 if (r != null) {
5213 mRecentTasks.remove(r.task);
Dianne Hackborn8894cc52011-07-01 16:28:17 -07005214 cleanUpRemovedTaskLocked(r,
5215 (flags&ActivityManager.REMOVE_TASK_KILL_PROCESS) != 0);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005216 return true;
5217 }
5218 } finally {
5219 Binder.restoreCallingIdentity(ident);
5220 }
5221 }
5222 return false;
5223 }
Dianne Hackbornd94df452011-02-16 18:53:31 -08005224
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005225 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
5226 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005227 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005228 TaskRecord jt = startTask;
5229
5230 // First look backwards
5231 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005232 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005233 if (r.task != jt) {
5234 jt = r.task;
5235 if (affinity.equals(jt.affinity)) {
5236 return j;
5237 }
5238 }
5239 }
5240
5241 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005242 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005243 jt = startTask;
5244 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005245 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005246 if (r.task != jt) {
5247 if (affinity.equals(jt.affinity)) {
5248 return j;
5249 }
5250 jt = r.task;
5251 }
5252 }
5253
5254 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005255 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005256 return N-1;
5257 }
5258
5259 return -1;
5260 }
5261
5262 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005263 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005264 */
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005265 public void moveTaskToFront(int task, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005266 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5267 "moveTaskToFront()");
5268
5269 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005270 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5271 Binder.getCallingUid(), "Task to front")) {
5272 return;
5273 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005274 final long origId = Binder.clearCallingIdentity();
5275 try {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005276 TaskRecord tr = taskForIdLocked(task);
5277 if (tr != null) {
5278 if ((flags&ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
5279 mMainStack.mUserLeaving = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005280 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005281 if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
5282 // Caller wants the home activity moved with it. To accomplish this,
5283 // we'll just move the home task to the top first.
5284 mMainStack.moveHomeToFrontLocked();
5285 }
5286 mMainStack.moveTaskToFrontLocked(tr, null);
5287 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005288 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005289 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
5290 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005291 if (hr.task.taskId == task) {
Dianne Hackbornd94df452011-02-16 18:53:31 -08005292 if ((flags&ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
5293 mMainStack.mUserLeaving = true;
5294 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005295 if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
5296 // Caller wants the home activity moved with it. To accomplish this,
5297 // we'll just move the home task to the top first.
5298 mMainStack.moveHomeToFrontLocked();
5299 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005300 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005301 return;
5302 }
5303 }
5304 } finally {
5305 Binder.restoreCallingIdentity(origId);
5306 }
5307 }
5308 }
5309
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005310 public void moveTaskToBack(int task) {
5311 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5312 "moveTaskToBack()");
5313
5314 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005315 if (mMainStack.mResumedActivity != null
5316 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005317 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5318 Binder.getCallingUid(), "Task to back")) {
5319 return;
5320 }
5321 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005322 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005323 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005324 Binder.restoreCallingIdentity(origId);
5325 }
5326 }
5327
5328 /**
5329 * Moves an activity, and all of the other activities within the same task, to the bottom
5330 * of the history stack. The activity's order within the task is unchanged.
5331 *
5332 * @param token A reference to the activity we wish to move
5333 * @param nonRoot If false then this only works if the activity is the root
5334 * of a task; if true it will work for any activity in a task.
5335 * @return Returns true if the move completed, false if not.
5336 */
5337 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
5338 synchronized(this) {
5339 final long origId = Binder.clearCallingIdentity();
5340 int taskId = getTaskForActivityLocked(token, !nonRoot);
5341 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005342 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005343 }
5344 Binder.restoreCallingIdentity(origId);
5345 }
5346 return false;
5347 }
5348
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005349 public void moveTaskBackwards(int task) {
5350 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5351 "moveTaskBackwards()");
5352
5353 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005354 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5355 Binder.getCallingUid(), "Task backwards")) {
5356 return;
5357 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005358 final long origId = Binder.clearCallingIdentity();
5359 moveTaskBackwardsLocked(task);
5360 Binder.restoreCallingIdentity(origId);
5361 }
5362 }
5363
5364 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005365 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005366 }
5367
5368 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
5369 synchronized(this) {
5370 return getTaskForActivityLocked(token, onlyRoot);
5371 }
5372 }
5373
5374 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005375 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005376 TaskRecord lastTask = null;
5377 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005378 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005379 if (r == token) {
5380 if (!onlyRoot || lastTask != r.task) {
5381 return r.task.taskId;
5382 }
5383 return -1;
5384 }
5385 lastTask = r.task;
5386 }
5387
5388 return -1;
5389 }
5390
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005391 public void finishOtherInstances(IBinder token, ComponentName className) {
5392 synchronized(this) {
5393 final long origId = Binder.clearCallingIdentity();
5394
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005395 int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005396 TaskRecord lastTask = null;
5397 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005398 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005399 if (r.realActivity.equals(className)
5400 && r != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005401 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005402 null, "others")) {
5403 i--;
5404 N--;
5405 }
5406 }
5407 lastTask = r.task;
5408 }
5409
5410 Binder.restoreCallingIdentity(origId);
5411 }
5412 }
5413
5414 // =========================================================
5415 // THUMBNAILS
5416 // =========================================================
5417
5418 public void reportThumbnail(IBinder token,
5419 Bitmap thumbnail, CharSequence description) {
5420 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
5421 final long origId = Binder.clearCallingIdentity();
5422 sendPendingThumbnail(null, token, thumbnail, description, true);
5423 Binder.restoreCallingIdentity(origId);
5424 }
5425
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005426 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005427 Bitmap thumbnail, CharSequence description, boolean always) {
5428 TaskRecord task = null;
5429 ArrayList receivers = null;
5430
5431 //System.out.println("Send pending thumbnail: " + r);
5432
5433 synchronized(this) {
5434 if (r == null) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07005435 r = mMainStack.isInStackLocked(token);
5436 if (r == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005437 return;
5438 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005439 }
Dianne Hackbornf26fd992011-04-08 18:14:09 -07005440 if (thumbnail == null && r.thumbHolder != null) {
5441 thumbnail = r.thumbHolder.lastThumbnail;
5442 description = r.thumbHolder.lastDescription;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005443 }
5444 if (thumbnail == null && !always) {
5445 // If there is no thumbnail, and this entry is not actually
5446 // going away, then abort for now and pick up the next
5447 // thumbnail we get.
5448 return;
5449 }
5450 task = r.task;
5451
5452 int N = mPendingThumbnails.size();
5453 int i=0;
5454 while (i<N) {
5455 PendingThumbnailsRecord pr =
5456 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
5457 //System.out.println("Looking in " + pr.pendingRecords);
5458 if (pr.pendingRecords.remove(r)) {
5459 if (receivers == null) {
5460 receivers = new ArrayList();
5461 }
5462 receivers.add(pr);
5463 if (pr.pendingRecords.size() == 0) {
5464 pr.finished = true;
5465 mPendingThumbnails.remove(i);
5466 N--;
5467 continue;
5468 }
5469 }
5470 i++;
5471 }
5472 }
5473
5474 if (receivers != null) {
5475 final int N = receivers.size();
5476 for (int i=0; i<N; i++) {
5477 try {
5478 PendingThumbnailsRecord pr =
5479 (PendingThumbnailsRecord)receivers.get(i);
5480 pr.receiver.newThumbnail(
5481 task != null ? task.taskId : -1, thumbnail, description);
5482 if (pr.finished) {
5483 pr.receiver.finished();
5484 }
5485 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005486 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005487 }
5488 }
5489 }
5490 }
5491
5492 // =========================================================
5493 // CONTENT PROVIDERS
5494 // =========================================================
5495
Jeff Brown10e89712011-07-08 18:52:57 -07005496 private final List<ProviderInfo> generateApplicationProvidersLocked(ProcessRecord app) {
5497 List<ProviderInfo> providers = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005498 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005499 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005500 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005501 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005502 } catch (RemoteException ex) {
5503 }
5504 if (providers != null) {
5505 final int N = providers.size();
5506 for (int i=0; i<N; i++) {
5507 ProviderInfo cpi =
5508 (ProviderInfo)providers.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07005509 ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005510 if (cpr == null) {
5511 cpr = new ContentProviderRecord(cpi, app.info);
5512 mProvidersByClass.put(cpi.name, cpr);
5513 }
5514 app.pubProviders.put(cpi.name, cpr);
5515 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005516 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005517 }
5518 }
5519 return providers;
5520 }
5521
5522 private final String checkContentProviderPermissionLocked(
Dianne Hackbornb424b632010-08-18 15:59:05 -07005523 ProviderInfo cpi, ProcessRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005524 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
5525 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
5526 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005527 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005528 == PackageManager.PERMISSION_GRANTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005529 return null;
5530 }
5531 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005532 cpi.applicationInfo.uid, cpi.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005533 == PackageManager.PERMISSION_GRANTED) {
5534 return null;
5535 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005536
5537 PathPermission[] pps = cpi.pathPermissions;
5538 if (pps != null) {
5539 int i = pps.length;
5540 while (i > 0) {
5541 i--;
5542 PathPermission pp = pps[i];
5543 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005544 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005545 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005546 return null;
5547 }
5548 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005549 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005550 == PackageManager.PERMISSION_GRANTED) {
5551 return null;
5552 }
5553 }
5554 }
5555
Dianne Hackbornb424b632010-08-18 15:59:05 -07005556 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
5557 if (perms != null) {
5558 for (Map.Entry<Uri, UriPermission> uri : perms.entrySet()) {
5559 if (uri.getKey().getAuthority().equals(cpi.authority)) {
5560 return null;
5561 }
5562 }
5563 }
5564
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005565 String msg;
5566 if (!cpi.exported) {
5567 msg = "Permission Denial: opening provider " + cpi.name
5568 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5569 + ", uid=" + callingUid + ") that is not exported from uid "
5570 + cpi.applicationInfo.uid;
5571 } else {
5572 msg = "Permission Denial: opening provider " + cpi.name
5573 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5574 + ", uid=" + callingUid + ") requires "
5575 + cpi.readPermission + " or " + cpi.writePermission;
5576 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005577 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005578 return msg;
5579 }
5580
5581 private final ContentProviderHolder getContentProviderImpl(
5582 IApplicationThread caller, String name) {
5583 ContentProviderRecord cpr;
5584 ProviderInfo cpi = null;
5585
5586 synchronized(this) {
5587 ProcessRecord r = null;
5588 if (caller != null) {
5589 r = getRecordForAppLocked(caller);
5590 if (r == null) {
5591 throw new SecurityException(
5592 "Unable to find app for caller " + caller
5593 + " (pid=" + Binder.getCallingPid()
5594 + ") when getting content provider " + name);
5595 }
5596 }
5597
5598 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07005599 cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005600 if (cpr != null) {
5601 cpi = cpr.info;
Dianne Hackbornb424b632010-08-18 15:59:05 -07005602 String msg;
5603 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5604 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005605 }
5606
5607 if (r != null && cpr.canRunHere(r)) {
5608 // This provider has been published or is in the process
5609 // of being published... but it is also allowed to run
5610 // in the caller's process, so don't make a connection
5611 // and just let the caller instantiate its own instance.
5612 if (cpr.provider != null) {
5613 // don't give caller the provider object, it needs
5614 // to make its own.
5615 cpr = new ContentProviderRecord(cpr);
5616 }
5617 return cpr;
5618 }
5619
5620 final long origId = Binder.clearCallingIdentity();
5621
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005622 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005623 // return it right away.
5624 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005625 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005626 "Adding provider requested by "
5627 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005628 + cpr.info.processName);
5629 Integer cnt = r.conProviders.get(cpr);
5630 if (cnt == null) {
5631 r.conProviders.put(cpr, new Integer(1));
5632 } else {
5633 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5634 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005635 cpr.clients.add(r);
Dianne Hackborn32907cf2010-06-10 17:50:20 -07005636 if (cpr.app != null && r.setAdj <= PERCEPTIBLE_APP_ADJ) {
5637 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07005638 // make sure to count it as being accessed and thus
5639 // back up on the LRU list. This is good because
5640 // content providers are often expensive to start.
5641 updateLruProcessLocked(cpr.app, false, true);
5642 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07005643 } else {
5644 cpr.externals++;
5645 }
5646
5647 if (cpr.app != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005648 updateOomAdjLocked(cpr.app);
5649 }
5650
5651 Binder.restoreCallingIdentity(origId);
5652
5653 } else {
5654 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005655 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005656 resolveContentProvider(name,
5657 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005658 } catch (RemoteException ex) {
5659 }
5660 if (cpi == null) {
5661 return null;
5662 }
5663
Dianne Hackbornb424b632010-08-18 15:59:05 -07005664 String msg;
5665 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5666 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005667 }
5668
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07005669 if (!mProcessesReady && !mDidUpdate && !mWaitingUpdate
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005670 && !cpi.processName.equals("system")) {
5671 // If this content provider does not run in the system
5672 // process, and the system is not yet ready to run other
5673 // processes, then fail fast instead of hanging.
5674 throw new IllegalArgumentException(
5675 "Attempt to launch content provider before system ready");
5676 }
5677
Dianne Hackborn860755f2010-06-03 18:47:52 -07005678 cpr = mProvidersByClass.get(cpi.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005679 final boolean firstClass = cpr == null;
5680 if (firstClass) {
5681 try {
5682 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005683 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005684 getApplicationInfo(
5685 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005686 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005687 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005688 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005689 + cpi.name);
5690 return null;
5691 }
5692 cpr = new ContentProviderRecord(cpi, ai);
5693 } catch (RemoteException ex) {
5694 // pm is in same process, this will never happen.
5695 }
5696 }
5697
5698 if (r != null && cpr.canRunHere(r)) {
5699 // If this is a multiprocess provider, then just return its
5700 // info and allow the caller to instantiate it. Only do
5701 // this if the provider is the same user as the caller's
5702 // process, or can run as root (so can be in any process).
5703 return cpr;
5704 }
5705
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005706 if (DEBUG_PROVIDER) {
5707 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08005708 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005709 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005710 }
5711
5712 // This is single process, and our app is now connecting to it.
5713 // See if we are already in the process of launching this
5714 // provider.
5715 final int N = mLaunchingProviders.size();
5716 int i;
5717 for (i=0; i<N; i++) {
5718 if (mLaunchingProviders.get(i) == cpr) {
5719 break;
5720 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005721 }
5722
5723 // If the provider is not already being launched, then get it
5724 // started.
5725 if (i >= N) {
5726 final long origId = Binder.clearCallingIdentity();
Dianne Hackborne7f97212011-02-24 14:40:20 -08005727
5728 try {
5729 // Content provider is now in use, its package can't be stopped.
5730 try {
5731 AppGlobals.getPackageManager().setPackageStoppedState(
5732 cpr.appInfo.packageName, false);
5733 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08005734 } catch (IllegalArgumentException e) {
5735 Slog.w(TAG, "Failed trying to unstop package "
5736 + cpr.appInfo.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08005737 }
5738
5739 ProcessRecord proc = startProcessLocked(cpi.processName,
5740 cpr.appInfo, false, 0, "content provider",
5741 new ComponentName(cpi.applicationInfo.packageName,
5742 cpi.name), false);
5743 if (proc == null) {
5744 Slog.w(TAG, "Unable to launch app "
5745 + cpi.applicationInfo.packageName + "/"
5746 + cpi.applicationInfo.uid + " for provider "
5747 + name + ": process is bad");
5748 return null;
5749 }
5750 cpr.launchingApp = proc;
5751 mLaunchingProviders.add(cpr);
5752 } finally {
5753 Binder.restoreCallingIdentity(origId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005754 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005755 }
5756
5757 // Make sure the provider is published (the same provider class
5758 // may be published under multiple names).
5759 if (firstClass) {
5760 mProvidersByClass.put(cpi.name, cpr);
5761 }
5762 mProvidersByName.put(name, cpr);
5763
5764 if (r != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005765 if (DEBUG_PROVIDER) Slog.v(TAG,
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005766 "Adding provider requested by "
5767 + r.processName + " from process "
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005768 + cpr.info.processName);
5769 Integer cnt = r.conProviders.get(cpr);
5770 if (cnt == null) {
5771 r.conProviders.put(cpr, new Integer(1));
5772 } else {
5773 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5774 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005775 cpr.clients.add(r);
5776 } else {
5777 cpr.externals++;
5778 }
5779 }
5780 }
5781
5782 // Wait for the provider to be published...
5783 synchronized (cpr) {
5784 while (cpr.provider == null) {
5785 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005786 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005787 + cpi.applicationInfo.packageName + "/"
5788 + cpi.applicationInfo.uid + " for provider "
5789 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005790 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005791 cpi.applicationInfo.packageName,
5792 cpi.applicationInfo.uid, name);
5793 return null;
5794 }
5795 try {
5796 cpr.wait();
5797 } catch (InterruptedException ex) {
5798 }
5799 }
5800 }
5801 return cpr;
5802 }
5803
5804 public final ContentProviderHolder getContentProvider(
5805 IApplicationThread caller, String name) {
5806 if (caller == null) {
5807 String msg = "null IApplicationThread when getting content provider "
5808 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005809 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005810 throw new SecurityException(msg);
5811 }
5812
5813 return getContentProviderImpl(caller, name);
5814 }
5815
5816 private ContentProviderHolder getContentProviderExternal(String name) {
5817 return getContentProviderImpl(null, name);
5818 }
5819
5820 /**
5821 * Drop a content provider from a ProcessRecord's bookkeeping
5822 * @param cpr
5823 */
5824 public void removeContentProvider(IApplicationThread caller, String name) {
5825 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005826 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005827 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005828 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005829 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005830 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005831 return;
5832 }
5833 final ProcessRecord r = getRecordForAppLocked(caller);
5834 if (r == null) {
5835 throw new SecurityException(
5836 "Unable to find app for caller " + caller +
5837 " when removing content provider " + name);
5838 }
5839 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005840 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005841 if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005842 + r.info.processName + " from process "
5843 + localCpr.appInfo.processName);
5844 if (localCpr.app == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005845 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08005846 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005847 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005848 return;
5849 } else {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005850 Integer cnt = r.conProviders.get(localCpr);
5851 if (cnt == null || cnt.intValue() <= 1) {
5852 localCpr.clients.remove(r);
5853 r.conProviders.remove(localCpr);
5854 } else {
5855 r.conProviders.put(localCpr, new Integer(cnt.intValue()-1));
5856 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005857 }
5858 updateOomAdjLocked();
5859 }
5860 }
5861
5862 private void removeContentProviderExternal(String name) {
5863 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005864 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005865 if(cpr == null) {
5866 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005867 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005868 return;
5869 }
5870
5871 //update content provider record entry info
Dianne Hackborn860755f2010-06-03 18:47:52 -07005872 ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005873 localCpr.externals--;
5874 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005875 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005876 }
5877 updateOomAdjLocked();
5878 }
5879 }
5880
5881 public final void publishContentProviders(IApplicationThread caller,
5882 List<ContentProviderHolder> providers) {
5883 if (providers == null) {
5884 return;
5885 }
5886
5887 synchronized(this) {
5888 final ProcessRecord r = getRecordForAppLocked(caller);
5889 if (r == null) {
5890 throw new SecurityException(
5891 "Unable to find app for caller " + caller
5892 + " (pid=" + Binder.getCallingPid()
5893 + ") when publishing content providers");
5894 }
5895
5896 final long origId = Binder.clearCallingIdentity();
5897
5898 final int N = providers.size();
5899 for (int i=0; i<N; i++) {
5900 ContentProviderHolder src = providers.get(i);
5901 if (src == null || src.info == null || src.provider == null) {
5902 continue;
5903 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005904 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005905 if (dst != null) {
5906 mProvidersByClass.put(dst.info.name, dst);
5907 String names[] = dst.info.authority.split(";");
5908 for (int j = 0; j < names.length; j++) {
5909 mProvidersByName.put(names[j], dst);
5910 }
5911
5912 int NL = mLaunchingProviders.size();
5913 int j;
5914 for (j=0; j<NL; j++) {
5915 if (mLaunchingProviders.get(j) == dst) {
5916 mLaunchingProviders.remove(j);
5917 j--;
5918 NL--;
5919 }
5920 }
5921 synchronized (dst) {
5922 dst.provider = src.provider;
5923 dst.app = r;
5924 dst.notifyAll();
5925 }
5926 updateOomAdjLocked(r);
5927 }
5928 }
5929
5930 Binder.restoreCallingIdentity(origId);
5931 }
5932 }
5933
5934 public static final void installSystemProviders() {
Jeff Brown10e89712011-07-08 18:52:57 -07005935 List<ProviderInfo> providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06005936 synchronized (mSelf) {
5937 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
5938 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08005939 if (providers != null) {
5940 for (int i=providers.size()-1; i>=0; i--) {
5941 ProviderInfo pi = (ProviderInfo)providers.get(i);
5942 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
5943 Slog.w(TAG, "Not installing system proc provider " + pi.name
5944 + ": not system .apk");
5945 providers.remove(i);
5946 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005947 }
5948 }
5949 }
Josh Bartel2ecce342010-02-25 10:55:48 -06005950 if (providers != null) {
5951 mSystemThread.installSystemProviders(providers);
5952 }
Svetoslav Ganov54d068e2011-03-02 12:58:40 -08005953
5954 mSelf.mCoreSettingsObserver = new CoreSettingsObserver(mSelf);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005955 }
5956
Dianne Hackborncca1f0e2010-09-26 18:34:53 -07005957 /**
5958 * Allows app to retrieve the MIME type of a URI without having permission
5959 * to access its content provider.
5960 *
5961 * CTS tests for this functionality can be run with "runtest cts-appsecurity".
5962 *
5963 * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
5964 * src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
5965 */
5966 public String getProviderMimeType(Uri uri) {
5967 final String name = uri.getAuthority();
5968 final long ident = Binder.clearCallingIdentity();
5969 ContentProviderHolder holder = null;
5970
5971 try {
5972 holder = getContentProviderExternal(name);
5973 if (holder != null) {
5974 return holder.provider.getType(uri);
5975 }
5976 } catch (RemoteException e) {
5977 Log.w(TAG, "Content provider dead retrieving " + uri, e);
5978 return null;
5979 } finally {
5980 if (holder != null) {
5981 removeContentProviderExternal(name);
5982 }
5983 Binder.restoreCallingIdentity(ident);
5984 }
5985
5986 return null;
5987 }
5988
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005989 // =========================================================
5990 // GLOBAL MANAGEMENT
5991 // =========================================================
5992
5993 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
5994 ApplicationInfo info, String customProcess) {
5995 String proc = customProcess != null ? customProcess : info.processName;
5996 BatteryStatsImpl.Uid.Proc ps = null;
5997 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5998 synchronized (stats) {
5999 ps = stats.getProcessStatsLocked(info.uid, proc);
6000 }
6001 return new ProcessRecord(ps, thread, info, proc);
6002 }
6003
6004 final ProcessRecord addAppLocked(ApplicationInfo info) {
6005 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
6006
6007 if (app == null) {
6008 app = newProcessRecordLocked(null, info, null);
6009 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006010 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006011 }
6012
Dianne Hackborne7f97212011-02-24 14:40:20 -08006013 // This package really, really can not be stopped.
6014 try {
6015 AppGlobals.getPackageManager().setPackageStoppedState(
6016 info.packageName, false);
6017 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08006018 } catch (IllegalArgumentException e) {
6019 Slog.w(TAG, "Failed trying to unstop package "
6020 + info.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08006021 }
6022
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006023 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
6024 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
6025 app.persistent = true;
6026 app.maxAdj = CORE_SERVER_ADJ;
6027 }
6028 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
6029 mPersistentStartingProcesses.add(app);
6030 startProcessLocked(app, "added application", app.processName);
6031 }
6032
6033 return app;
6034 }
6035
6036 public void unhandledBack() {
6037 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
6038 "unhandledBack()");
6039
6040 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006041 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08006042 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006043 TAG, "Performing unhandledBack(): stack size = " + count);
6044 if (count > 1) {
6045 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006046 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006047 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
6048 Binder.restoreCallingIdentity(origId);
6049 }
6050 }
6051 }
6052
6053 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
6054 String name = uri.getAuthority();
6055 ContentProviderHolder cph = getContentProviderExternal(name);
6056 ParcelFileDescriptor pfd = null;
6057 if (cph != null) {
6058 // We record the binder invoker's uid in thread-local storage before
6059 // going to the content provider to open the file. Later, in the code
6060 // that handles all permissions checks, we look for this uid and use
6061 // that rather than the Activity Manager's own uid. The effect is that
6062 // we do the check against the caller's permissions even though it looks
6063 // to the content provider like the Activity Manager itself is making
6064 // the request.
6065 sCallerIdentity.set(new Identity(
6066 Binder.getCallingPid(), Binder.getCallingUid()));
6067 try {
6068 pfd = cph.provider.openFile(uri, "r");
6069 } catch (FileNotFoundException e) {
6070 // do nothing; pfd will be returned null
6071 } finally {
6072 // Ensure that whatever happens, we clean up the identity state
6073 sCallerIdentity.remove();
6074 }
6075
6076 // We've got the fd now, so we're done with the provider.
6077 removeContentProviderExternal(name);
6078 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006079 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006080 }
6081 return pfd;
6082 }
6083
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006084 // Actually is sleeping or shutting down or whatever else in the future
6085 // is an inactive state.
6086 public boolean isSleeping() {
6087 return mSleeping || mShuttingDown;
6088 }
6089
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006090 public void goingToSleep() {
6091 synchronized(this) {
6092 mSleeping = true;
6093 mWindowManager.setEventDispatching(false);
6094
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006095 mMainStack.stopIfSleepingLocked();
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07006096
6097 // Initialize the wake times of all processes.
Dianne Hackborn287952c2010-09-22 22:34:31 -07006098 checkExcessivePowerUsageLocked(false);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07006099 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
6100 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07006101 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006102 }
6103 }
6104
Dianne Hackborn55280a92009-05-07 15:53:46 -07006105 public boolean shutdown(int timeout) {
6106 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
6107 != PackageManager.PERMISSION_GRANTED) {
6108 throw new SecurityException("Requires permission "
6109 + android.Manifest.permission.SHUTDOWN);
6110 }
6111
6112 boolean timedout = false;
6113
6114 synchronized(this) {
6115 mShuttingDown = true;
6116 mWindowManager.setEventDispatching(false);
6117
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006118 if (mMainStack.mResumedActivity != null) {
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006119 mMainStack.stopIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07006120 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006121 while (mMainStack.mResumedActivity != null
6122 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07006123 long delay = endTime - System.currentTimeMillis();
6124 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006125 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07006126 timedout = true;
6127 break;
6128 }
6129 try {
6130 this.wait();
6131 } catch (InterruptedException e) {
6132 }
6133 }
6134 }
6135 }
6136
6137 mUsageStatsService.shutdown();
6138 mBatteryStatsService.shutdown();
6139
6140 return timedout;
6141 }
6142
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006143 public final void activitySlept(IBinder token) {
6144 if (localLOGV) Slog.v(
6145 TAG, "Activity slept: token=" + token);
6146
6147 ActivityRecord r = null;
6148
6149 final long origId = Binder.clearCallingIdentity();
6150
6151 synchronized (this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07006152 r = mMainStack.isInStackLocked(token);
6153 if (r != null) {
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006154 mMainStack.activitySleptLocked(r);
6155 }
6156 }
6157
6158 Binder.restoreCallingIdentity(origId);
6159 }
6160
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006161 public void wakingUp() {
6162 synchronized(this) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006163 mWindowManager.setEventDispatching(true);
6164 mSleeping = false;
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006165 mMainStack.awakeFromSleepingLocked();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006166 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006167 }
6168 }
6169
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006170 public void stopAppSwitches() {
6171 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
6172 != PackageManager.PERMISSION_GRANTED) {
6173 throw new SecurityException("Requires permission "
6174 + android.Manifest.permission.STOP_APP_SWITCHES);
6175 }
6176
6177 synchronized(this) {
6178 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
6179 + APP_SWITCH_DELAY_TIME;
6180 mDidAppSwitch = false;
6181 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
6182 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
6183 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
6184 }
6185 }
6186
6187 public void resumeAppSwitches() {
6188 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
6189 != PackageManager.PERMISSION_GRANTED) {
6190 throw new SecurityException("Requires permission "
6191 + android.Manifest.permission.STOP_APP_SWITCHES);
6192 }
6193
6194 synchronized(this) {
6195 // Note that we don't execute any pending app switches... we will
6196 // let those wait until either the timeout, or the next start
6197 // activity request.
6198 mAppSwitchesAllowedTime = 0;
6199 }
6200 }
6201
6202 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
6203 String name) {
6204 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
6205 return true;
6206 }
6207
6208 final int perm = checkComponentPermission(
6209 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08006210 callingUid, -1, true);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006211 if (perm == PackageManager.PERMISSION_GRANTED) {
6212 return true;
6213 }
6214
Joe Onorato8a9b2202010-02-26 18:56:32 -08006215 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006216 return false;
6217 }
6218
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006219 public void setDebugApp(String packageName, boolean waitForDebugger,
6220 boolean persistent) {
6221 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
6222 "setDebugApp()");
6223
6224 // Note that this is not really thread safe if there are multiple
6225 // callers into it at the same time, but that's not a situation we
6226 // care about.
6227 if (persistent) {
6228 final ContentResolver resolver = mContext.getContentResolver();
6229 Settings.System.putString(
6230 resolver, Settings.System.DEBUG_APP,
6231 packageName);
6232 Settings.System.putInt(
6233 resolver, Settings.System.WAIT_FOR_DEBUGGER,
6234 waitForDebugger ? 1 : 0);
6235 }
6236
6237 synchronized (this) {
6238 if (!persistent) {
6239 mOrigDebugApp = mDebugApp;
6240 mOrigWaitForDebugger = mWaitForDebugger;
6241 }
6242 mDebugApp = packageName;
6243 mWaitForDebugger = waitForDebugger;
6244 mDebugTransient = !persistent;
6245 if (packageName != null) {
6246 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006247 forceStopPackageLocked(packageName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006248 Binder.restoreCallingIdentity(origId);
6249 }
6250 }
6251 }
6252
6253 public void setAlwaysFinish(boolean enabled) {
6254 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
6255 "setAlwaysFinish()");
6256
6257 Settings.System.putInt(
6258 mContext.getContentResolver(),
6259 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
6260
6261 synchronized (this) {
6262 mAlwaysFinishActivities = enabled;
6263 }
6264 }
6265
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006266 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006267 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006268 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006269 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006270 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006271 }
6272 }
6273
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08006274 public boolean isUserAMonkey() {
6275 // For now the fact that there is a controller implies
6276 // we have a monkey.
6277 synchronized (this) {
6278 return mController != null;
6279 }
6280 }
6281
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006282 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06006283 synchronized (this) {
6284 mWatchers.register(watcher);
6285 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006286 }
6287
6288 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06006289 synchronized (this) {
6290 mWatchers.unregister(watcher);
6291 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006292 }
6293
Jeff Sharkeya4620792011-05-20 15:29:23 -07006294 public void registerProcessObserver(IProcessObserver observer) {
6295 mProcessObservers.register(observer);
6296 }
6297
6298 public void unregisterProcessObserver(IProcessObserver observer) {
6299 mProcessObservers.unregister(observer);
6300 }
6301
Daniel Sandler69a48172010-06-23 16:29:36 -04006302 public void setImmersive(IBinder token, boolean immersive) {
6303 synchronized(this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07006304 ActivityRecord r = mMainStack.isInStackLocked(token);
6305 if (r == null) {
Daniel Sandler69a48172010-06-23 16:29:36 -04006306 throw new IllegalArgumentException();
6307 }
Daniel Sandler69a48172010-06-23 16:29:36 -04006308 r.immersive = immersive;
6309 }
6310 }
6311
6312 public boolean isImmersive(IBinder token) {
6313 synchronized (this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07006314 ActivityRecord r = mMainStack.isInStackLocked(token);
6315 if (r == null) {
Daniel Sandler69a48172010-06-23 16:29:36 -04006316 throw new IllegalArgumentException();
6317 }
Daniel Sandler69a48172010-06-23 16:29:36 -04006318 return r.immersive;
6319 }
6320 }
6321
6322 public boolean isTopActivityImmersive() {
6323 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006324 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Daniel Sandler69a48172010-06-23 16:29:36 -04006325 return (r != null) ? r.immersive : false;
6326 }
6327 }
6328
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006329 public final void enterSafeMode() {
6330 synchronized(this) {
6331 // It only makes sense to do this before the system is ready
6332 // and started launching other packages.
6333 if (!mSystemReady) {
6334 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006335 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006336 } catch (RemoteException e) {
6337 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006338 }
6339 }
6340 }
6341
Jeff Brownb09abc12011-01-13 21:08:27 -08006342 public final void showSafeModeOverlay() {
6343 View v = LayoutInflater.from(mContext).inflate(
6344 com.android.internal.R.layout.safe_mode, null);
6345 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
6346 lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
6347 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
6348 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
6349 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
6350 lp.format = v.getBackground().getOpacity();
6351 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
6352 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
6353 ((WindowManager)mContext.getSystemService(
6354 Context.WINDOW_SERVICE)).addView(v, lp);
6355 }
6356
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006357 public void noteWakeupAlarm(IIntentSender sender) {
6358 if (!(sender instanceof PendingIntentRecord)) {
6359 return;
6360 }
6361 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
6362 synchronized (stats) {
6363 if (mBatteryStatsService.isOnBattery()) {
6364 mBatteryStatsService.enforceCallingPermission();
6365 PendingIntentRecord rec = (PendingIntentRecord)sender;
6366 int MY_UID = Binder.getCallingUid();
6367 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
6368 BatteryStatsImpl.Uid.Pkg pkg =
6369 stats.getPackageStatsLocked(uid, rec.key.packageName);
6370 pkg.incWakeupsLocked();
6371 }
6372 }
6373 }
6374
Dianne Hackborn64825172011-03-02 21:32:58 -08006375 public boolean killPids(int[] pids, String pReason, boolean secure) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006376 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006377 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006378 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006379 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006380 // XXX Note: don't acquire main activity lock here, because the window
6381 // manager calls in with its locks held.
6382
6383 boolean killed = false;
6384 synchronized (mPidsSelfLocked) {
6385 int[] types = new int[pids.length];
6386 int worstType = 0;
6387 for (int i=0; i<pids.length; i++) {
6388 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6389 if (proc != null) {
6390 int type = proc.setAdj;
6391 types[i] = type;
6392 if (type > worstType) {
6393 worstType = type;
6394 }
6395 }
6396 }
6397
Dianne Hackborn64825172011-03-02 21:32:58 -08006398 // If the worst oom_adj is somewhere in the hidden proc LRU range,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006399 // then constrain it so we will kill all hidden procs.
6400 if (worstType < EMPTY_APP_ADJ && worstType > HIDDEN_APP_MIN_ADJ) {
6401 worstType = HIDDEN_APP_MIN_ADJ;
6402 }
Dianne Hackborn64825172011-03-02 21:32:58 -08006403
6404 // If this is not a secure call, don't let it kill processes that
6405 // are important.
6406 if (!secure && worstType < SECONDARY_SERVER_ADJ) {
6407 worstType = SECONDARY_SERVER_ADJ;
6408 }
6409
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006410 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006411 for (int i=0; i<pids.length; i++) {
6412 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6413 if (proc == null) {
6414 continue;
6415 }
6416 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006417 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07006418 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006419 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
6420 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006421 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006422 proc.killedBackground = true;
6423 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006424 }
6425 }
6426 }
6427 return killed;
6428 }
6429
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006430 public final void startRunning(String pkg, String cls, String action,
6431 String data) {
6432 synchronized(this) {
6433 if (mStartRunning) {
6434 return;
6435 }
6436 mStartRunning = true;
6437 mTopComponent = pkg != null && cls != null
6438 ? new ComponentName(pkg, cls) : null;
6439 mTopAction = action != null ? action : Intent.ACTION_MAIN;
6440 mTopData = data;
6441 if (!mSystemReady) {
6442 return;
6443 }
6444 }
6445
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006446 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006447 }
6448
6449 private void retrieveSettings() {
6450 final ContentResolver resolver = mContext.getContentResolver();
6451 String debugApp = Settings.System.getString(
6452 resolver, Settings.System.DEBUG_APP);
6453 boolean waitForDebugger = Settings.System.getInt(
6454 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
6455 boolean alwaysFinishActivities = Settings.System.getInt(
6456 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
6457
6458 Configuration configuration = new Configuration();
6459 Settings.System.getConfiguration(resolver, configuration);
6460
6461 synchronized (this) {
6462 mDebugApp = mOrigDebugApp = debugApp;
6463 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
6464 mAlwaysFinishActivities = alwaysFinishActivities;
6465 // This happens before any activities are started, so we can
6466 // change mConfiguration in-place.
6467 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08006468 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006469 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006470 }
6471 }
6472
6473 public boolean testIsSystemReady() {
6474 // no need to synchronize(this) just to read & return the value
6475 return mSystemReady;
6476 }
6477
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006478 private static File getCalledPreBootReceiversFile() {
6479 File dataDir = Environment.getDataDirectory();
6480 File systemDir = new File(dataDir, "system");
6481 File fname = new File(systemDir, "called_pre_boots.dat");
6482 return fname;
6483 }
6484
6485 private static ArrayList<ComponentName> readLastDonePreBootReceivers() {
6486 ArrayList<ComponentName> lastDoneReceivers = new ArrayList<ComponentName>();
6487 File file = getCalledPreBootReceiversFile();
6488 FileInputStream fis = null;
6489 try {
6490 fis = new FileInputStream(file);
6491 DataInputStream dis = new DataInputStream(new BufferedInputStream(fis, 2048));
6492 int vers = dis.readInt();
6493 String codename = dis.readUTF();
6494 if (vers == android.os.Build.VERSION.SDK_INT
6495 && codename.equals(android.os.Build.VERSION.CODENAME)) {
6496 int num = dis.readInt();
6497 while (num > 0) {
6498 num--;
6499 String pkg = dis.readUTF();
6500 String cls = dis.readUTF();
6501 lastDoneReceivers.add(new ComponentName(pkg, cls));
6502 }
6503 }
6504 } catch (FileNotFoundException e) {
6505 } catch (IOException e) {
6506 Slog.w(TAG, "Failure reading last done pre-boot receivers", e);
6507 } finally {
6508 if (fis != null) {
6509 try {
6510 fis.close();
6511 } catch (IOException e) {
6512 }
6513 }
6514 }
6515 return lastDoneReceivers;
6516 }
6517
6518 private static void writeLastDonePreBootReceivers(ArrayList<ComponentName> list) {
6519 File file = getCalledPreBootReceiversFile();
6520 FileOutputStream fos = null;
6521 DataOutputStream dos = null;
6522 try {
6523 Slog.i(TAG, "Writing new set of last done pre-boot receivers...");
6524 fos = new FileOutputStream(file);
6525 dos = new DataOutputStream(new BufferedOutputStream(fos, 2048));
6526 dos.writeInt(android.os.Build.VERSION.SDK_INT);
6527 dos.writeUTF(android.os.Build.VERSION.CODENAME);
6528 dos.writeInt(list.size());
6529 for (int i=0; i<list.size(); i++) {
6530 dos.writeUTF(list.get(i).getPackageName());
6531 dos.writeUTF(list.get(i).getClassName());
6532 }
6533 } catch (IOException e) {
6534 Slog.w(TAG, "Failure writing last done pre-boot receivers", e);
6535 file.delete();
6536 } finally {
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07006537 FileUtils.sync(fos);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006538 if (dos != null) {
6539 try {
6540 dos.close();
6541 } catch (IOException e) {
6542 // TODO Auto-generated catch block
6543 e.printStackTrace();
6544 }
6545 }
6546 }
6547 }
6548
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006549 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006550 synchronized(this) {
6551 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006552 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006553 return;
6554 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006555
6556 // Check to see if there are any update receivers to run.
6557 if (!mDidUpdate) {
6558 if (mWaitingUpdate) {
6559 return;
6560 }
6561 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
6562 List<ResolveInfo> ris = null;
6563 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006564 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006565 intent, null, 0);
6566 } catch (RemoteException e) {
6567 }
6568 if (ris != null) {
6569 for (int i=ris.size()-1; i>=0; i--) {
6570 if ((ris.get(i).activityInfo.applicationInfo.flags
6571 &ApplicationInfo.FLAG_SYSTEM) == 0) {
6572 ris.remove(i);
6573 }
6574 }
6575 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006576
6577 ArrayList<ComponentName> lastDoneReceivers = readLastDonePreBootReceivers();
6578
6579 final ArrayList<ComponentName> doneReceivers = new ArrayList<ComponentName>();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006580 for (int i=0; i<ris.size(); i++) {
6581 ActivityInfo ai = ris.get(i).activityInfo;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006582 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6583 if (lastDoneReceivers.contains(comp)) {
6584 ris.remove(i);
6585 i--;
6586 }
6587 }
6588
6589 for (int i=0; i<ris.size(); i++) {
6590 ActivityInfo ai = ris.get(i).activityInfo;
6591 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6592 doneReceivers.add(comp);
6593 intent.setComponent(comp);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006594 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08006595 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006596 finisher = new IIntentReceiver.Stub() {
6597 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07006598 String data, Bundle extras, boolean ordered,
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006599 boolean sticky) {
6600 // The raw IIntentReceiver interface is called
6601 // with the AM lock held, so redispatch to
6602 // execute our code without the lock.
6603 mHandler.post(new Runnable() {
6604 public void run() {
6605 synchronized (ActivityManagerService.this) {
6606 mDidUpdate = true;
6607 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006608 writeLastDonePreBootReceivers(doneReceivers);
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006609 systemReady(goingCallback);
6610 }
6611 });
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006612 }
6613 };
6614 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006615 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006616 broadcastIntentLocked(null, null, intent, null, finisher,
6617 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08006618 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006619 mWaitingUpdate = true;
6620 }
6621 }
6622 }
6623 if (mWaitingUpdate) {
6624 return;
6625 }
6626 mDidUpdate = true;
6627 }
6628
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006629 mSystemReady = true;
6630 if (!mStartRunning) {
6631 return;
6632 }
6633 }
6634
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006635 ArrayList<ProcessRecord> procsToKill = null;
6636 synchronized(mPidsSelfLocked) {
6637 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
6638 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
6639 if (!isAllowedWhileBooting(proc.info)){
6640 if (procsToKill == null) {
6641 procsToKill = new ArrayList<ProcessRecord>();
6642 }
6643 procsToKill.add(proc);
6644 }
6645 }
6646 }
6647
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006648 synchronized(this) {
6649 if (procsToKill != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006650 for (int i=procsToKill.size()-1; i>=0; i--) {
6651 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08006652 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn130b0d22011-07-26 22:07:48 -07006653 removeProcessLocked(proc, true, false);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006654 }
6655 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006656
6657 // Now that we have cleaned up any update processes, we
6658 // are ready to start launching real processes and know that
6659 // we won't trample on them any more.
6660 mProcessesReady = true;
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006661 }
6662
Joe Onorato8a9b2202010-02-26 18:56:32 -08006663 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006664 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006665 SystemClock.uptimeMillis());
6666
6667 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006668 // Make sure we have no pre-ready processes sitting around.
6669
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006670 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
6671 ResolveInfo ri = mContext.getPackageManager()
6672 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07006673 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006674 CharSequence errorMsg = null;
6675 if (ri != null) {
6676 ActivityInfo ai = ri.activityInfo;
6677 ApplicationInfo app = ai.applicationInfo;
6678 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
6679 mTopAction = Intent.ACTION_FACTORY_TEST;
6680 mTopData = null;
6681 mTopComponent = new ComponentName(app.packageName,
6682 ai.name);
6683 } else {
6684 errorMsg = mContext.getResources().getText(
6685 com.android.internal.R.string.factorytest_not_system);
6686 }
6687 } else {
6688 errorMsg = mContext.getResources().getText(
6689 com.android.internal.R.string.factorytest_no_action);
6690 }
6691 if (errorMsg != null) {
6692 mTopAction = null;
6693 mTopData = null;
6694 mTopComponent = null;
6695 Message msg = Message.obtain();
6696 msg.what = SHOW_FACTORY_ERROR_MSG;
6697 msg.getData().putCharSequence("msg", errorMsg);
6698 mHandler.sendMessage(msg);
6699 }
6700 }
6701 }
6702
6703 retrieveSettings();
6704
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006705 if (goingCallback != null) goingCallback.run();
6706
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006707 synchronized (this) {
6708 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
6709 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006710 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07006711 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006712 if (apps != null) {
6713 int N = apps.size();
6714 int i;
6715 for (i=0; i<N; i++) {
6716 ApplicationInfo info
6717 = (ApplicationInfo)apps.get(i);
6718 if (info != null &&
6719 !info.packageName.equals("android")) {
6720 addAppLocked(info);
6721 }
6722 }
6723 }
6724 } catch (RemoteException ex) {
6725 // pm is in same process, this will never happen.
6726 }
6727 }
6728
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006729 // Start up initial activity.
6730 mBooting = true;
6731
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006732 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006733 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006734 Message msg = Message.obtain();
6735 msg.what = SHOW_UID_ERROR_MSG;
6736 mHandler.sendMessage(msg);
6737 }
6738 } catch (RemoteException e) {
6739 }
6740
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006741 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006742 }
6743 }
6744
Dan Egnorb7f03672009-12-09 16:22:32 -08006745 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006746 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006747 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006748 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006749 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006750 startAppProblemLocked(app);
6751 app.stopFreezingAllLocked();
6752 return handleAppCrashLocked(app);
6753 }
6754
Dan Egnorb7f03672009-12-09 16:22:32 -08006755 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006756 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006757 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006758 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006759 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
6760 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006761 startAppProblemLocked(app);
6762 app.stopFreezingAllLocked();
6763 }
6764
6765 /**
6766 * Generate a process error record, suitable for attachment to a ProcessRecord.
6767 *
6768 * @param app The ProcessRecord in which the error occurred.
6769 * @param condition Crashing, Application Not Responding, etc. Values are defined in
6770 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08006771 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006772 * @param shortMsg Short message describing the crash.
6773 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08006774 * @param stackTrace Full crash stack trace, may be null.
6775 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006776 * @return Returns a fully-formed AppErrorStateInfo record.
6777 */
6778 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006779 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006780 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08006781
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006782 report.condition = condition;
6783 report.processName = app.processName;
6784 report.pid = app.pid;
6785 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08006786 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006787 report.shortMsg = shortMsg;
6788 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08006789 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006790
6791 return report;
6792 }
6793
Dan Egnor42471dd2010-01-07 17:25:22 -08006794 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006795 synchronized (this) {
6796 app.crashing = false;
6797 app.crashingReport = null;
6798 app.notResponding = false;
6799 app.notRespondingReport = null;
6800 if (app.anrDialog == fromDialog) {
6801 app.anrDialog = null;
6802 }
6803 if (app.waitDialog == fromDialog) {
6804 app.waitDialog = null;
6805 }
6806 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08006807 handleAppCrashLocked(app);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07006808 Slog.i(ActivityManagerService.TAG, "Killing " + app + ": user's request");
Dianne Hackborn8633e682010-04-22 16:03:41 -07006809 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
6810 app.processName, app.setAdj, "user's request after error");
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07006811 Process.killProcessQuiet(app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006812 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006813 }
6814 }
Dan Egnor42471dd2010-01-07 17:25:22 -08006815
Dan Egnorb7f03672009-12-09 16:22:32 -08006816 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006817 long now = SystemClock.uptimeMillis();
6818
6819 Long crashTime = mProcessCrashTimes.get(app.info.processName,
6820 app.info.uid);
6821 if (crashTime != null && now < crashTime+MIN_CRASH_INTERVAL) {
6822 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006823 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006824 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006825 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006826 app.info.processName, app.info.uid);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006827 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
6828 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006829 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006830 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006831 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006832 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006833 }
6834 }
6835 if (!app.persistent) {
6836 // We don't want to start this process again until the user
6837 // explicitly does so... but for persistent process, we really
6838 // need to keep it running. If a persistent process is actually
6839 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08006840 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006841 app.info.processName);
6842 mBadProcesses.put(app.info.processName, app.info.uid, now);
6843 app.bad = true;
6844 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
6845 app.removed = true;
Dianne Hackborn130b0d22011-07-26 22:07:48 -07006846 // Don't let services in this process be restarted and potentially
6847 // annoy the user repeatedly. Unless it is persistent, since those
6848 // processes run critical code.
6849 removeProcessLocked(app, false, false);
Dianne Hackborncb44d962011-03-10 17:02:27 -08006850 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006851 return false;
6852 }
Dianne Hackborncb44d962011-03-10 17:02:27 -08006853 mMainStack.resumeTopActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006854 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006855 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006856 if (r.app == app) {
6857 // If the top running activity is from this crashing
6858 // process, then terminate it to avoid getting in a loop.
6859 Slog.w(TAG, " Force finishing activity "
6860 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006861 int index = mMainStack.indexOfTokenLocked(r);
6862 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006863 Activity.RESULT_CANCELED, null, "crashed");
Dianne Hackborn070783f2010-12-29 16:46:28 -08006864 // Also terminate any activities below it that aren't yet
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006865 // stopped, to avoid a situation where one will get
6866 // re-start our crashing activity once it gets resumed again.
6867 index--;
6868 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006869 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006870 if (r.state == ActivityState.RESUMED
6871 || r.state == ActivityState.PAUSING
6872 || r.state == ActivityState.PAUSED) {
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -08006873 if (!r.isHomeActivity || mHomeProcess != r.app) {
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006874 Slog.w(TAG, " Force finishing activity "
6875 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006876 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006877 Activity.RESULT_CANCELED, null, "crashed");
6878 }
6879 }
6880 }
6881 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006882 }
6883
6884 // Bump up the crash count of any services currently running in the proc.
6885 if (app.services.size() != 0) {
6886 // Any services running in the application need to be placed
6887 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07006888 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006889 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006890 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006891 sr.crashCount++;
6892 }
6893 }
Mattias Larssona4fd0072010-06-22 22:37:03 +02006894
6895 // If the crashing process is what we consider to be the "home process" and it has been
6896 // replaced by a third-party app, clear the package preferred activities from packages
6897 // with a home activity running in the process to prevent a repeatedly crashing app
6898 // from blocking the user to manually clear the list.
6899 if (app == mHomeProcess && mHomeProcess.activities.size() > 0
6900 && (mHomeProcess.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
6901 Iterator it = mHomeProcess.activities.iterator();
6902 while (it.hasNext()) {
Jean-Baptiste Queru5ea89f72010-07-30 09:30:31 -07006903 ActivityRecord r = (ActivityRecord)it.next();
Mattias Larssona4fd0072010-06-22 22:37:03 +02006904 if (r.isHomeActivity) {
6905 Log.i(TAG, "Clearing package preferred activities from " + r.packageName);
6906 try {
6907 ActivityThread.getPackageManager()
6908 .clearPackagePreferredActivities(r.packageName);
6909 } catch (RemoteException c) {
6910 // pm is in same process, this will never happen.
6911 }
6912 }
6913 }
6914 }
6915
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006916 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
6917 return true;
6918 }
6919
6920 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006921 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
6922 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006923 skipCurrentReceiverLocked(app);
6924 }
6925
6926 void skipCurrentReceiverLocked(ProcessRecord app) {
6927 boolean reschedule = false;
6928 BroadcastRecord r = app.curReceiver;
6929 if (r != null) {
6930 // The current broadcast is waiting for this app's receiver
6931 // to be finished. Looks like that's not going to happen, so
6932 // let the broadcast continue.
Jeff Brown4d94a762010-09-23 11:33:28 -07006933 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006934 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6935 r.resultExtras, r.resultAbort, true);
6936 reschedule = true;
6937 }
6938 r = mPendingBroadcast;
6939 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006940 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006941 "skip & discard pending app " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -07006942 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006943 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
6944 r.resultExtras, r.resultAbort, true);
6945 reschedule = true;
6946 }
6947 if (reschedule) {
6948 scheduleBroadcastsLocked();
6949 }
6950 }
6951
Dan Egnor60d87622009-12-16 16:32:58 -08006952 /**
6953 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
6954 * The application process will exit immediately after this call returns.
6955 * @param app object of the crashing app, null for the system server
6956 * @param crashInfo describing the exception
6957 */
6958 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
Dianne Hackborncb44d962011-03-10 17:02:27 -08006959 ProcessRecord r = findAppProcess(app, "Crash");
Dan Egnor60d87622009-12-16 16:32:58 -08006960
6961 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
6962 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08006963 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08006964 crashInfo.exceptionClassName,
6965 crashInfo.exceptionMessage,
6966 crashInfo.throwFileName,
6967 crashInfo.throwLineNumber);
6968
Dan Egnor42471dd2010-01-07 17:25:22 -08006969 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08006970
6971 crashApplication(r, crashInfo);
6972 }
6973
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006974 public void handleApplicationStrictModeViolation(
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006975 IBinder app,
6976 int violationMask,
6977 StrictMode.ViolationInfo info) {
Dianne Hackborncb44d962011-03-10 17:02:27 -08006978 ProcessRecord r = findAppProcess(app, "StrictMode");
6979 if (r == null) {
6980 return;
6981 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07006982
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07006983 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -08006984 Integer stackFingerprint = info.hashCode();
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006985 boolean logIt = true;
6986 synchronized (mAlreadyLoggedViolatedStacks) {
6987 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
6988 logIt = false;
6989 // TODO: sub-sample into EventLog for these, with
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07006990 // the info.durationMillis? Then we'd get
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07006991 // the relative pain numbers, without logging all
6992 // the stack traces repeatedly. We'd want to do
6993 // likewise in the client code, which also does
6994 // dup suppression, before the Binder call.
6995 } else {
6996 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
6997 mAlreadyLoggedViolatedStacks.clear();
6998 }
6999 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
7000 }
7001 }
7002 if (logIt) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007003 logStrictModeViolationToDropBox(r, info);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07007004 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07007005 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07007006
7007 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
7008 AppErrorResult result = new AppErrorResult();
7009 synchronized (this) {
7010 final long origId = Binder.clearCallingIdentity();
7011
7012 Message msg = Message.obtain();
7013 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
7014 HashMap<String, Object> data = new HashMap<String, Object>();
7015 data.put("result", result);
7016 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07007017 data.put("violationMask", violationMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007018 data.put("info", info);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07007019 msg.obj = data;
7020 mHandler.sendMessage(msg);
7021
7022 Binder.restoreCallingIdentity(origId);
7023 }
7024 int res = result.get();
Dianne Hackbornb424b632010-08-18 15:59:05 -07007025 Slog.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07007026 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07007027 }
7028
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007029 // Depending on the policy in effect, there could be a bunch of
7030 // these in quick succession so we try to batch these together to
7031 // minimize disk writes, number of dropbox entries, and maximize
7032 // compression, by having more fewer, larger records.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007033 private void logStrictModeViolationToDropBox(
7034 ProcessRecord process,
7035 StrictMode.ViolationInfo info) {
7036 if (info == null) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007037 return;
7038 }
7039 final boolean isSystemApp = process == null ||
7040 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
7041 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
7042 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
7043 final DropBoxManager dbox = (DropBoxManager)
7044 mContext.getSystemService(Context.DROPBOX_SERVICE);
7045
7046 // Exit early if the dropbox isn't configured to accept this report type.
7047 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
7048
7049 boolean bufferWasEmpty;
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007050 boolean needsFlush;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007051 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
7052 synchronized (sb) {
7053 bufferWasEmpty = sb.length() == 0;
7054 appendDropBoxProcessHeaders(process, sb);
7055 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
7056 sb.append("System-App: ").append(isSystemApp).append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007057 sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
7058 if (info.violationNumThisLoop != 0) {
7059 sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
7060 }
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07007061 if (info.numAnimationsRunning != 0) {
7062 sb.append("Animations-Running: ").append(info.numAnimationsRunning).append("\n");
7063 }
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07007064 if (info.broadcastIntentAction != null) {
7065 sb.append("Broadcast-Intent-Action: ").append(info.broadcastIntentAction).append("\n");
7066 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08007067 if (info.durationMillis != -1) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007068 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007069 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08007070 if (info.numInstances != -1) {
7071 sb.append("Instance-Count: ").append(info.numInstances).append("\n");
7072 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08007073 if (info.tags != null) {
7074 for (String tag : info.tags) {
7075 sb.append("Span-Tag: ").append(tag).append("\n");
7076 }
7077 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007078 sb.append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007079 if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
7080 sb.append(info.crashInfo.stackTrace);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007081 }
7082 sb.append("\n");
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007083
7084 // Only buffer up to ~64k. Various logging bits truncate
7085 // things at 128k.
7086 needsFlush = (sb.length() > 64 * 1024);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007087 }
7088
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007089 // Flush immediately if the buffer's grown too large, or this
7090 // is a non-system app. Non-system apps are isolated with a
7091 // different tag & policy and not batched.
7092 //
7093 // Batching is useful during internal testing with
7094 // StrictMode settings turned up high. Without batching,
7095 // thousands of separate files could be created on boot.
7096 if (!isSystemApp || needsFlush) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007097 new Thread("Error dump: " + dropboxTag) {
7098 @Override
7099 public void run() {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007100 String report;
7101 synchronized (sb) {
7102 report = sb.toString();
7103 sb.delete(0, sb.length());
7104 sb.trimToSize();
7105 }
7106 if (report.length() != 0) {
7107 dbox.addText(dropboxTag, report);
7108 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007109 }
7110 }.start();
7111 return;
7112 }
7113
7114 // System app batching:
7115 if (!bufferWasEmpty) {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007116 // An existing dropbox-writing thread is outstanding, so
7117 // we don't need to start it up. The existing thread will
7118 // catch the buffer appends we just did.
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007119 return;
7120 }
7121
7122 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
7123 // (After this point, we shouldn't access AMS internal data structures.)
7124 new Thread("Error dump: " + dropboxTag) {
7125 @Override
7126 public void run() {
7127 // 5 second sleep to let stacks arrive and be batched together
7128 try {
7129 Thread.sleep(5000); // 5 seconds
7130 } catch (InterruptedException e) {}
7131
7132 String errorReport;
7133 synchronized (mStrictModeBuffer) {
7134 errorReport = mStrictModeBuffer.toString();
7135 if (errorReport.length() == 0) {
7136 return;
7137 }
7138 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
7139 mStrictModeBuffer.trimToSize();
7140 }
7141 dbox.addText(dropboxTag, errorReport);
7142 }
7143 }.start();
7144 }
7145
Dan Egnor60d87622009-12-16 16:32:58 -08007146 /**
7147 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
7148 * @param app object of the crashing app, null for the system server
7149 * @param tag reported by the caller
7150 * @param crashInfo describing the context of the error
7151 * @return true if the process should exit immediately (WTF is fatal)
7152 */
7153 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08007154 ApplicationErrorReport.CrashInfo crashInfo) {
Dianne Hackborncb44d962011-03-10 17:02:27 -08007155 ProcessRecord r = findAppProcess(app, "WTF");
Dan Egnor60d87622009-12-16 16:32:58 -08007156
7157 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
7158 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08007159 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08007160 tag, crashInfo.exceptionMessage);
7161
Dan Egnor42471dd2010-01-07 17:25:22 -08007162 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08007163
Dianne Hackborn1ab43772011-03-15 14:38:02 -07007164 if (r != null && r.pid != Process.myPid() &&
7165 Settings.Secure.getInt(mContext.getContentResolver(),
7166 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08007167 crashApplication(r, crashInfo);
7168 return true;
7169 } else {
7170 return false;
7171 }
7172 }
7173
7174 /**
7175 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
7176 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
7177 */
Dianne Hackborncb44d962011-03-10 17:02:27 -08007178 private ProcessRecord findAppProcess(IBinder app, String reason) {
Dan Egnor60d87622009-12-16 16:32:58 -08007179 if (app == null) {
7180 return null;
7181 }
7182
7183 synchronized (this) {
7184 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
7185 final int NA = apps.size();
7186 for (int ia=0; ia<NA; ia++) {
7187 ProcessRecord p = apps.valueAt(ia);
7188 if (p.thread != null && p.thread.asBinder() == app) {
7189 return p;
7190 }
7191 }
7192 }
7193
Dianne Hackborncb44d962011-03-10 17:02:27 -08007194 Slog.w(TAG, "Can't find mystery application for " + reason
7195 + " from pid=" + Binder.getCallingPid()
7196 + " uid=" + Binder.getCallingUid() + ": " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08007197 return null;
7198 }
7199 }
7200
7201 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007202 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
7203 * to append various headers to the dropbox log text.
Dan Egnor60d87622009-12-16 16:32:58 -08007204 */
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07007205 private void appendDropBoxProcessHeaders(ProcessRecord process, StringBuilder sb) {
Vairavan Srinivasan68a4e0a2011-02-14 20:45:59 -08007206 // Watchdog thread ends up invoking this function (with
7207 // a null ProcessRecord) to add the stack file to dropbox.
7208 // Do not acquire a lock on this (am) in such cases, as it
7209 // could cause a potential deadlock, if and when watchdog
7210 // is invoked due to unavailability of lock on am and it
7211 // would prevent watchdog from killing system_server.
7212 if (process == null) {
7213 sb.append("Process: system_server\n");
7214 return;
7215 }
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07007216 // Note: ProcessRecord 'process' is guarded by the service
7217 // instance. (notably process.pkgList, which could otherwise change
7218 // concurrently during execution of this method)
7219 synchronized (this) {
Vairavan Srinivasan68a4e0a2011-02-14 20:45:59 -08007220 if (process.pid == MY_PID) {
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07007221 sb.append("Process: system_server\n");
7222 } else {
7223 sb.append("Process: ").append(process.processName).append("\n");
7224 }
Dan Egnora455d192010-03-12 08:52:28 -08007225 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007226 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08007227 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
7228 for (String pkg : process.pkgList) {
7229 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08007230 try {
Dan Egnora455d192010-03-12 08:52:28 -08007231 PackageInfo pi = pm.getPackageInfo(pkg, 0);
7232 if (pi != null) {
7233 sb.append(" v").append(pi.versionCode);
7234 if (pi.versionName != null) {
7235 sb.append(" (").append(pi.versionName).append(")");
7236 }
7237 }
7238 } catch (RemoteException e) {
7239 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08007240 }
Dan Egnora455d192010-03-12 08:52:28 -08007241 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08007242 }
Dan Egnora455d192010-03-12 08:52:28 -08007243 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007244 }
7245
7246 private static String processClass(ProcessRecord process) {
7247 if (process == null || process.pid == MY_PID) {
7248 return "system_server";
7249 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
7250 return "system_app";
7251 } else {
7252 return "data_app";
7253 }
7254 }
7255
7256 /**
7257 * Write a description of an error (crash, WTF, ANR) to the drop box.
7258 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
7259 * @param process which caused the error, null means the system server
7260 * @param activity which triggered the error, null if unknown
7261 * @param parent activity related to the error, null if unknown
7262 * @param subject line related to the error, null if absent
7263 * @param report in long form describing the error, null if absent
7264 * @param logFile to include in the report, null if none
7265 * @param crashInfo giving an application stack trace, null if absent
7266 */
7267 public void addErrorToDropBox(String eventType,
7268 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
7269 final String report, final File logFile,
7270 final ApplicationErrorReport.CrashInfo crashInfo) {
7271 // NOTE -- this must never acquire the ActivityManagerService lock,
7272 // otherwise the watchdog may be prevented from resetting the system.
7273
7274 final String dropboxTag = processClass(process) + "_" + eventType;
7275 final DropBoxManager dbox = (DropBoxManager)
7276 mContext.getSystemService(Context.DROPBOX_SERVICE);
7277
7278 // Exit early if the dropbox isn't configured to accept this report type.
7279 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
7280
7281 final StringBuilder sb = new StringBuilder(1024);
7282 appendDropBoxProcessHeaders(process, sb);
Dan Egnora455d192010-03-12 08:52:28 -08007283 if (activity != null) {
7284 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
7285 }
7286 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
7287 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
7288 }
7289 if (parent != null && parent != activity) {
7290 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
7291 }
7292 if (subject != null) {
7293 sb.append("Subject: ").append(subject).append("\n");
7294 }
7295 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
Christian Lindeberg03d2ca62010-09-28 14:52:20 +02007296 if (Debug.isDebuggerConnected()) {
7297 sb.append("Debugger: Connected\n");
7298 }
Dan Egnora455d192010-03-12 08:52:28 -08007299 sb.append("\n");
7300
7301 // Do the rest in a worker thread to avoid blocking the caller on I/O
7302 // (After this point, we shouldn't access AMS internal data structures.)
7303 Thread worker = new Thread("Error dump: " + dropboxTag) {
7304 @Override
7305 public void run() {
7306 if (report != null) {
7307 sb.append(report);
7308 }
7309 if (logFile != null) {
7310 try {
7311 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
7312 } catch (IOException e) {
7313 Slog.e(TAG, "Error reading " + logFile, e);
7314 }
7315 }
7316 if (crashInfo != null && crashInfo.stackTrace != null) {
7317 sb.append(crashInfo.stackTrace);
7318 }
7319
7320 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
7321 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
7322 if (lines > 0) {
7323 sb.append("\n");
7324
7325 // Merge several logcat streams, and take the last N lines
7326 InputStreamReader input = null;
7327 try {
7328 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
7329 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
7330 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
7331
7332 try { logcat.getOutputStream().close(); } catch (IOException e) {}
7333 try { logcat.getErrorStream().close(); } catch (IOException e) {}
7334 input = new InputStreamReader(logcat.getInputStream());
7335
7336 int num;
7337 char[] buf = new char[8192];
7338 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
7339 } catch (IOException e) {
7340 Slog.e(TAG, "Error running logcat", e);
7341 } finally {
7342 if (input != null) try { input.close(); } catch (IOException e) {}
7343 }
7344 }
7345
7346 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08007347 }
Dan Egnora455d192010-03-12 08:52:28 -08007348 };
7349
7350 if (process == null || process.pid == MY_PID) {
7351 worker.run(); // We may be about to die -- need to run this synchronously
7352 } else {
7353 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08007354 }
7355 }
7356
7357 /**
7358 * Bring up the "unexpected error" dialog box for a crashing app.
7359 * Deal with edge cases (intercepts from instrumented applications,
7360 * ActivityController, error intent receivers, that sort of thing).
7361 * @param r the application crashing
7362 * @param crashInfo describing the failure
7363 */
7364 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007365 long timeMillis = System.currentTimeMillis();
7366 String shortMsg = crashInfo.exceptionClassName;
7367 String longMsg = crashInfo.exceptionMessage;
7368 String stackTrace = crashInfo.stackTrace;
7369 if (shortMsg != null && longMsg != null) {
7370 longMsg = shortMsg + ": " + longMsg;
7371 } else if (shortMsg != null) {
7372 longMsg = shortMsg;
7373 }
7374
Dan Egnor60d87622009-12-16 16:32:58 -08007375 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007376 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007377 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007378 try {
7379 String name = r != null ? r.processName : null;
7380 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08007381 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08007382 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007383 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007384 + " at watcher's request");
7385 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08007386 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007387 }
7388 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007389 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007390 }
7391 }
7392
7393 final long origId = Binder.clearCallingIdentity();
7394
7395 // If this process is running instrumentation, finish it.
7396 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007397 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007398 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08007399 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
7400 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007401 Bundle info = new Bundle();
7402 info.putString("shortMsg", shortMsg);
7403 info.putString("longMsg", longMsg);
7404 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
7405 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007406 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007407 }
7408
Dan Egnor60d87622009-12-16 16:32:58 -08007409 // If we can't identify the process or it's already exceeded its crash quota,
7410 // quit right away without showing a crash dialog.
7411 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007412 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007413 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007414 }
7415
7416 Message msg = Message.obtain();
7417 msg.what = SHOW_ERROR_MSG;
7418 HashMap data = new HashMap();
7419 data.put("result", result);
7420 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007421 msg.obj = data;
7422 mHandler.sendMessage(msg);
7423
7424 Binder.restoreCallingIdentity(origId);
7425 }
7426
7427 int res = result.get();
7428
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007429 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007430 synchronized (this) {
7431 if (r != null) {
7432 mProcessCrashTimes.put(r.info.processName, r.info.uid,
7433 SystemClock.uptimeMillis());
7434 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007435 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007436 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007437 }
7438 }
7439
7440 if (appErrorIntent != null) {
7441 try {
7442 mContext.startActivity(appErrorIntent);
7443 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007444 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007445 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007446 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007447 }
Dan Egnorb7f03672009-12-09 16:22:32 -08007448
7449 Intent createAppErrorIntentLocked(ProcessRecord r,
7450 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
7451 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007452 if (report == null) {
7453 return null;
7454 }
7455 Intent result = new Intent(Intent.ACTION_APP_ERROR);
7456 result.setComponent(r.errorReportReceiver);
7457 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
7458 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
7459 return result;
7460 }
7461
Dan Egnorb7f03672009-12-09 16:22:32 -08007462 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
7463 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007464 if (r.errorReportReceiver == null) {
7465 return null;
7466 }
7467
7468 if (!r.crashing && !r.notResponding) {
7469 return null;
7470 }
7471
Dan Egnorb7f03672009-12-09 16:22:32 -08007472 ApplicationErrorReport report = new ApplicationErrorReport();
7473 report.packageName = r.info.packageName;
7474 report.installerPackageName = r.errorReportReceiver.getPackageName();
7475 report.processName = r.processName;
7476 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01007477 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007478
Dan Egnorb7f03672009-12-09 16:22:32 -08007479 if (r.crashing) {
7480 report.type = ApplicationErrorReport.TYPE_CRASH;
7481 report.crashInfo = crashInfo;
7482 } else if (r.notResponding) {
7483 report.type = ApplicationErrorReport.TYPE_ANR;
7484 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007485
Dan Egnorb7f03672009-12-09 16:22:32 -08007486 report.anrInfo.activity = r.notRespondingReport.tag;
7487 report.anrInfo.cause = r.notRespondingReport.shortMsg;
7488 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007489 }
7490
Dan Egnorb7f03672009-12-09 16:22:32 -08007491 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007492 }
7493
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007494 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
7495 // assume our apps are happy - lazy create the list
7496 List<ActivityManager.ProcessErrorStateInfo> errList = null;
7497
7498 synchronized (this) {
7499
7500 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007501 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7502 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007503 if ((app.thread != null) && (app.crashing || app.notResponding)) {
7504 // This one's in trouble, so we'll generate a report for it
7505 // crashes are higher priority (in case there's a crash *and* an anr)
7506 ActivityManager.ProcessErrorStateInfo report = null;
7507 if (app.crashing) {
7508 report = app.crashingReport;
7509 } else if (app.notResponding) {
7510 report = app.notRespondingReport;
7511 }
7512
7513 if (report != null) {
7514 if (errList == null) {
7515 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
7516 }
7517 errList.add(report);
7518 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007519 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007520 " crashing = " + app.crashing +
7521 " notResponding = " + app.notResponding);
7522 }
7523 }
7524 }
7525 }
7526
7527 return errList;
7528 }
7529
7530 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
7531 // Lazy instantiation of list
7532 List<ActivityManager.RunningAppProcessInfo> runList = null;
7533 synchronized (this) {
7534 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007535 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7536 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007537 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
7538 // Generate process state info for running application
7539 ActivityManager.RunningAppProcessInfo currApp =
7540 new ActivityManager.RunningAppProcessInfo(app.processName,
7541 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07007542 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007543 if (mHeavyWeightProcess == app) {
Dianne Hackborn482566e2010-09-03 12:51:28 -07007544 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007545 }
Dianne Hackborn42499172010-10-15 18:45:07 -07007546 if (app.persistent) {
7547 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_PERSISTENT;
7548 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007549 int adj = app.curAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007550 if (adj >= EMPTY_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007551 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
7552 } else if (adj >= HIDDEN_APP_MIN_ADJ) {
7553 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
The Android Open Source Project4df24232009-03-05 14:34:35 -08007554 currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
7555 } else if (adj >= HOME_APP_ADJ) {
7556 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
7557 currApp.lru = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007558 } else if (adj >= SECONDARY_SERVER_ADJ) {
7559 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007560 } else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackborn5383f502010-10-22 12:59:20 -07007561 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07007562 } else if (adj >= PERCEPTIBLE_APP_ADJ) {
7563 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007564 } else if (adj >= VISIBLE_APP_ADJ) {
7565 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
7566 } else {
7567 currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
7568 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007569 currApp.importanceReasonCode = app.adjTypeCode;
7570 if (app.adjSource instanceof ProcessRecord) {
7571 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007572 } else if (app.adjSource instanceof ActivityRecord) {
7573 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007574 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
7575 }
7576 if (app.adjTarget instanceof ComponentName) {
7577 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
7578 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007579 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007580 // + " lru=" + currApp.lru);
7581 if (runList == null) {
7582 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
7583 }
7584 runList.add(currApp);
7585 }
7586 }
7587 }
7588 return runList;
7589 }
7590
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007591 public List<ApplicationInfo> getRunningExternalApplications() {
7592 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
7593 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
7594 if (runningApps != null && runningApps.size() > 0) {
7595 Set<String> extList = new HashSet<String>();
7596 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
7597 if (app.pkgList != null) {
7598 for (String pkg : app.pkgList) {
7599 extList.add(pkg);
7600 }
7601 }
7602 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007603 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007604 for (String pkg : extList) {
7605 try {
7606 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
7607 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
7608 retList.add(info);
7609 }
7610 } catch (RemoteException e) {
7611 }
7612 }
7613 }
7614 return retList;
7615 }
7616
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007617 @Override
7618 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007619 if (checkCallingPermission(android.Manifest.permission.DUMP)
7620 != PackageManager.PERMISSION_GRANTED) {
7621 pw.println("Permission Denial: can't dump ActivityManager from from pid="
7622 + Binder.getCallingPid()
7623 + ", uid=" + Binder.getCallingUid()
7624 + " without permission "
7625 + android.Manifest.permission.DUMP);
7626 return;
7627 }
7628
7629 boolean dumpAll = false;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007630 boolean dumpClient = false;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007631
7632 int opti = 0;
7633 while (opti < args.length) {
7634 String opt = args[opti];
7635 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
7636 break;
7637 }
7638 opti++;
7639 if ("-a".equals(opt)) {
7640 dumpAll = true;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007641 } else if ("-c".equals(opt)) {
7642 dumpClient = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007643 } else if ("-h".equals(opt)) {
7644 pw.println("Activity manager dump options:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007645 pw.println(" [-a] [-c] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007646 pw.println(" cmd may be one of:");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007647 pw.println(" a[ctivities]: activity stack state");
7648 pw.println(" b[roadcasts]: broadcast state");
7649 pw.println(" i[ntents]: pending intent state");
7650 pw.println(" p[rocesses]: process state");
7651 pw.println(" o[om]: out of memory management");
7652 pw.println(" prov[iders]: content provider state");
7653 pw.println(" s[ervices]: service state");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007654 pw.println(" service [COMP_SPEC]: service client-side state");
7655 pw.println(" cmd may also be a COMP_SPEC to dump activities.");
7656 pw.println(" COMP_SPEC may also be a component name (com.foo/.myApp),");
7657 pw.println(" a partial substring in a component name, an");
7658 pw.println(" ActivityRecord hex object identifier, or");
Dianne Hackbornf9302322011-06-14 18:36:14 -07007659 pw.println(" \"all\" for all objects, or");
7660 pw.println(" \"top\" for the top activity.");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007661 pw.println(" -a: include all available server state.");
7662 pw.println(" -c: include client state.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007663 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007664 } else {
7665 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007666 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007667 }
7668
7669 // Is the caller requesting to dump a particular piece of data?
7670 if (opti < args.length) {
7671 String cmd = args[opti];
7672 opti++;
7673 if ("activities".equals(cmd) || "a".equals(cmd)) {
7674 synchronized (this) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007675 dumpActivitiesLocked(fd, pw, args, opti, true, dumpClient);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007676 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007677 return;
7678 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
7679 synchronized (this) {
7680 dumpBroadcastsLocked(fd, pw, args, opti, true);
7681 }
7682 return;
7683 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
7684 synchronized (this) {
7685 dumpPendingIntentsLocked(fd, pw, args, opti, true);
7686 }
7687 return;
7688 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
7689 synchronized (this) {
7690 dumpProcessesLocked(fd, pw, args, opti, true);
7691 }
7692 return;
Dianne Hackborn287952c2010-09-22 22:34:31 -07007693 } else if ("oom".equals(cmd) || "o".equals(cmd)) {
7694 synchronized (this) {
7695 dumpOomLocked(fd, pw, args, opti, true);
7696 }
7697 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007698 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
7699 synchronized (this) {
7700 dumpProvidersLocked(fd, pw, args, opti, true);
7701 }
7702 return;
7703 } else if ("service".equals(cmd)) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007704 String[] newArgs;
7705 String name;
7706 if (opti >= args.length) {
7707 name = null;
7708 newArgs = EMPTY_STRING_ARRAY;
7709 } else {
7710 name = args[opti];
7711 opti++;
7712 newArgs = new String[args.length - opti];
7713 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
7714 }
7715 if (!dumpService(fd, pw, name, newArgs, 0, dumpAll)) {
7716 pw.println("No services match: " + name);
7717 pw.println("Use -h for help.");
7718 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007719 return;
7720 } else if ("services".equals(cmd) || "s".equals(cmd)) {
7721 synchronized (this) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007722 dumpServicesLocked(fd, pw, args, opti, true, dumpClient);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007723 }
7724 return;
Dianne Hackborn625ac272010-09-17 18:29:22 -07007725 } else {
7726 // Dumping a single activity?
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007727 if (!dumpActivity(fd, pw, cmd, args, opti, dumpAll)) {
7728 pw.println("Bad activity command, or no activities match: " + cmd);
7729 pw.println("Use -h for help.");
Dianne Hackborn625ac272010-09-17 18:29:22 -07007730 }
Dianne Hackborn30d71892010-12-11 10:37:55 -08007731 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007732 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007733 }
7734
7735 // No piece of data specified, dump everything.
7736 synchronized (this) {
7737 boolean needSep;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007738 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007739 if (needSep) {
7740 pw.println(" ");
7741 }
7742 if (dumpAll) {
7743 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007744 }
7745 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
7746 if (needSep) {
7747 pw.println(" ");
7748 }
7749 if (dumpAll) {
7750 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007751 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007752 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007753 if (needSep) {
7754 pw.println(" ");
7755 }
7756 if (dumpAll) {
7757 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007758 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007759 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll, dumpClient);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007760 if (needSep) {
7761 pw.println(" ");
7762 }
7763 if (dumpAll) {
7764 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007765 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007766 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, dumpClient);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007767 if (needSep) {
7768 pw.println(" ");
7769 }
7770 if (dumpAll) {
7771 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007772 }
7773 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
7774 }
7775 }
7776
7777 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007778 int opti, boolean dumpAll, boolean dumpClient) {
7779 pw.println("ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)");
7780 pw.println(" Main stack:");
7781 dumpHistoryList(fd, pw, mMainStack.mHistory, " ", "Hist", true, !dumpAll, dumpClient);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007782 pw.println(" ");
7783 pw.println(" Running activities (most recent first):");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007784 dumpHistoryList(fd, pw, mMainStack.mLRUActivities, " ", "Run", false, !dumpAll, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007785 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007786 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007787 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007788 dumpHistoryList(fd, pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false,
7789 !dumpAll, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007790 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007791 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007792 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007793 pw.println(" Activities waiting to stop:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007794 dumpHistoryList(fd, pw, mMainStack.mStoppingActivities, " ", "Stop", false,
7795 !dumpAll, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007796 }
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08007797 if (mMainStack.mGoingToSleepActivities.size() > 0) {
7798 pw.println(" ");
7799 pw.println(" Activities waiting to sleep:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007800 dumpHistoryList(fd, pw, mMainStack.mGoingToSleepActivities, " ", "Sleep", false,
7801 !dumpAll, false);
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08007802 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007803 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007804 pw.println(" ");
7805 pw.println(" Activities waiting to finish:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007806 dumpHistoryList(fd, pw, mMainStack.mFinishingActivities, " ", "Fin", false,
7807 !dumpAll, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007808 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007809
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007810 pw.println(" ");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007811 if (mMainStack.mPausingActivity != null) {
7812 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
7813 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007814 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007815 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007816 if (dumpAll) {
7817 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
7818 pw.println(" mSleepTimeout: " + mMainStack.mSleepTimeout);
7819 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007820
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007821 if (mRecentTasks.size() > 0) {
7822 pw.println();
7823 pw.println(" Recent tasks:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007824
7825 final int N = mRecentTasks.size();
7826 for (int i=0; i<N; i++) {
7827 TaskRecord tr = mRecentTasks.get(i);
7828 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
7829 pw.println(tr);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007830 if (dumpAll) {
7831 mRecentTasks.get(i).dump(pw, " ");
7832 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007833 }
7834 }
7835
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007836 if (dumpAll) {
7837 pw.println(" ");
7838 pw.println(" mCurTask: " + mCurTask);
7839 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007840
7841 return true;
7842 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07007843
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007844 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7845 int opti, boolean dumpAll) {
7846 boolean needSep = false;
7847 int numPers = 0;
7848
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007849 pw.println("ACTIVITY MANAGER RUNNING PROCESSES (dumpsys activity processes)");
7850
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007851 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007852 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
7853 final int NA = procs.size();
7854 for (int ia=0; ia<NA; ia++) {
7855 if (!needSep) {
7856 pw.println(" All known processes:");
7857 needSep = true;
7858 }
7859 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007860 pw.print(r.persistent ? " *PERS*" : " *APP*");
7861 pw.print(" UID "); pw.print(procs.keyAt(ia));
7862 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007863 r.dump(pw, " ");
7864 if (r.persistent) {
7865 numPers++;
7866 }
7867 }
7868 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007869 }
7870
7871 if (mLruProcesses.size() > 0) {
7872 if (needSep) pw.println(" ");
7873 needSep = true;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007874 pw.println(" Process LRU list (most recent first):");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007875 dumpProcessOomList(pw, this, mLruProcesses, " ",
7876 "Proc", "PERS", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007877 needSep = true;
7878 }
7879
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007880 if (dumpAll) {
7881 synchronized (mPidsSelfLocked) {
7882 if (mPidsSelfLocked.size() > 0) {
7883 if (needSep) pw.println(" ");
7884 needSep = true;
7885 pw.println(" PID mappings:");
7886 for (int i=0; i<mPidsSelfLocked.size(); i++) {
7887 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
7888 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
7889 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007890 }
7891 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007892 }
7893
7894 if (mForegroundProcesses.size() > 0) {
7895 if (needSep) pw.println(" ");
7896 needSep = true;
7897 pw.println(" Foreground Processes:");
7898 for (int i=0; i<mForegroundProcesses.size(); i++) {
7899 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
7900 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007901 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007902 }
7903
7904 if (mPersistentStartingProcesses.size() > 0) {
7905 if (needSep) pw.println(" ");
7906 needSep = true;
7907 pw.println(" Persisent processes that are starting:");
7908 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007909 "Starting Norm", "Restarting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007910 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007911
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007912 if (mRemovedProcesses.size() > 0) {
7913 if (needSep) pw.println(" ");
7914 needSep = true;
7915 pw.println(" Processes that are being removed:");
7916 dumpProcessList(pw, this, mRemovedProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007917 "Removed Norm", "Removed PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007918 }
7919
7920 if (mProcessesOnHold.size() > 0) {
7921 if (needSep) pw.println(" ");
7922 needSep = true;
7923 pw.println(" Processes that are on old until the system is ready:");
7924 dumpProcessList(pw, this, mProcessesOnHold, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07007925 "OnHold Norm", "OnHold PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007926 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007927
Dianne Hackborn287952c2010-09-22 22:34:31 -07007928 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007929
7930 if (mProcessCrashTimes.getMap().size() > 0) {
7931 if (needSep) pw.println(" ");
7932 needSep = true;
7933 pw.println(" Time since processes crashed:");
7934 long now = SystemClock.uptimeMillis();
7935 for (Map.Entry<String, SparseArray<Long>> procs
7936 : mProcessCrashTimes.getMap().entrySet()) {
7937 SparseArray<Long> uids = procs.getValue();
7938 final int N = uids.size();
7939 for (int i=0; i<N; i++) {
7940 pw.print(" Process "); pw.print(procs.getKey());
7941 pw.print(" uid "); pw.print(uids.keyAt(i));
7942 pw.print(": last crashed ");
7943 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007944 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07007945 }
7946 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007947 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007948
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007949 if (mBadProcesses.getMap().size() > 0) {
7950 if (needSep) pw.println(" ");
7951 needSep = true;
7952 pw.println(" Bad processes:");
7953 for (Map.Entry<String, SparseArray<Long>> procs
7954 : mBadProcesses.getMap().entrySet()) {
7955 SparseArray<Long> uids = procs.getValue();
7956 final int N = uids.size();
7957 for (int i=0; i<N; i++) {
7958 pw.print(" Bad process "); pw.print(procs.getKey());
7959 pw.print(" uid "); pw.print(uids.keyAt(i));
7960 pw.print(": crashed at time ");
7961 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007962 }
7963 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007964 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007965
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007966 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007967 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -07007968 if (mHeavyWeightProcess != null) {
7969 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
7970 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007971 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007972 if (dumpAll) {
7973 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackborn3d0724d2011-05-12 15:39:41 -07007974 if (mCompatModePackages.getPackages().size() > 0) {
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07007975 pw.println(" mScreenCompatPackages:");
7976 for (Map.Entry<String, Integer> entry
7977 : mCompatModePackages.getPackages().entrySet()) {
7978 String pkg = entry.getKey();
7979 int mode = entry.getValue();
7980 pw.print(" "); pw.print(pkg); pw.print(": ");
7981 pw.print(mode); pw.println();
7982 }
Dianne Hackbornaa9d84c2011-05-09 19:00:59 -07007983 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007984 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007985 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
7986 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
7987 || mOrigWaitForDebugger) {
7988 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
7989 + " mDebugTransient=" + mDebugTransient
7990 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
7991 }
7992 if (mAlwaysFinishActivities || mController != null) {
7993 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
7994 + " mController=" + mController);
7995 }
7996 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007997 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007998 pw.println(" mStartRunning=" + mStartRunning
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07007999 + " mProcessesReady=" + mProcessesReady
8000 + " mSystemReady=" + mSystemReady);
8001 pw.println(" mBooting=" + mBooting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008002 + " mBooted=" + mBooted
8003 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008004 pw.print(" mLastPowerCheckRealtime=");
8005 TimeUtils.formatDuration(mLastPowerCheckRealtime, pw);
8006 pw.println("");
8007 pw.print(" mLastPowerCheckUptime=");
8008 TimeUtils.formatDuration(mLastPowerCheckUptime, pw);
8009 pw.println("");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008010 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
8011 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07008012 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008013 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008014
8015 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008016 }
8017
Dianne Hackborn287952c2010-09-22 22:34:31 -07008018 boolean dumpProcessesToGc(FileDescriptor fd, PrintWriter pw, String[] args,
8019 int opti, boolean needSep, boolean dumpAll) {
8020 if (mProcessesToGc.size() > 0) {
8021 if (needSep) pw.println(" ");
8022 needSep = true;
8023 pw.println(" Processes that are waiting to GC:");
8024 long now = SystemClock.uptimeMillis();
8025 for (int i=0; i<mProcessesToGc.size(); i++) {
8026 ProcessRecord proc = mProcessesToGc.get(i);
8027 pw.print(" Process "); pw.println(proc);
8028 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
8029 pw.print(", last gced=");
8030 pw.print(now-proc.lastRequestedGc);
8031 pw.print(" ms ago, last lowMem=");
8032 pw.print(now-proc.lastLowMemory);
8033 pw.println(" ms ago");
8034
8035 }
8036 }
8037 return needSep;
8038 }
8039
8040 boolean dumpOomLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8041 int opti, boolean dumpAll) {
8042 boolean needSep = false;
8043
8044 if (mLruProcesses.size() > 0) {
8045 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>(mLruProcesses);
8046
8047 Comparator<ProcessRecord> comparator = new Comparator<ProcessRecord>() {
8048 @Override
8049 public int compare(ProcessRecord object1, ProcessRecord object2) {
8050 if (object1.setAdj != object2.setAdj) {
8051 return object1.setAdj > object2.setAdj ? -1 : 1;
8052 }
8053 if (object1.setSchedGroup != object2.setSchedGroup) {
8054 return object1.setSchedGroup > object2.setSchedGroup ? -1 : 1;
8055 }
8056 if (object1.keeping != object2.keeping) {
8057 return object1.keeping ? -1 : 1;
8058 }
8059 if (object1.pid != object2.pid) {
8060 return object1.pid > object2.pid ? -1 : 1;
8061 }
8062 return 0;
8063 }
8064 };
8065
8066 Collections.sort(procs, comparator);
8067
8068 if (needSep) pw.println(" ");
8069 needSep = true;
Dianne Hackbornc68c9132011-07-29 01:25:18 -07008070 pw.println(" OOM levels:");
8071 pw.print(" SYSTEM_ADJ: "); pw.println(SYSTEM_ADJ);
8072 pw.print(" CORE_SERVER_ADJ: "); pw.println(CORE_SERVER_ADJ);
8073 pw.print(" FOREGROUND_APP_ADJ: "); pw.println(FOREGROUND_APP_ADJ);
8074 pw.print(" VISIBLE_APP_ADJ: "); pw.println(VISIBLE_APP_ADJ);
8075 pw.print(" PERCEPTIBLE_APP_ADJ: "); pw.println(PERCEPTIBLE_APP_ADJ);
8076 pw.print(" HEAVY_WEIGHT_APP_ADJ: "); pw.println(HEAVY_WEIGHT_APP_ADJ);
8077 pw.print(" BACKUP_APP_ADJ: "); pw.println(BACKUP_APP_ADJ);
8078 pw.print(" SECONDARY_SERVER_ADJ: "); pw.println(SECONDARY_SERVER_ADJ);
8079 pw.print(" HOME_APP_ADJ: "); pw.println(HOME_APP_ADJ);
8080 pw.print(" HIDDEN_APP_MIN_ADJ: "); pw.println(HIDDEN_APP_MIN_ADJ);
8081 pw.print(" EMPTY_APP_ADJ: "); pw.println(EMPTY_APP_ADJ);
8082
8083 if (needSep) pw.println(" ");
8084 needSep = true;
Dianne Hackborn287952c2010-09-22 22:34:31 -07008085 pw.println(" Process OOM control:");
8086 dumpProcessOomList(pw, this, procs, " ",
8087 "Proc", "PERS", true);
8088 needSep = true;
8089 }
8090
8091 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
8092
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008093 pw.println();
Dianne Hackborn287952c2010-09-22 22:34:31 -07008094 pw.println(" mHomeProcess: " + mHomeProcess);
8095 if (mHeavyWeightProcess != null) {
8096 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
8097 }
8098
8099 return true;
8100 }
8101
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008102 /**
8103 * There are three ways to call this:
8104 * - no service specified: dump all the services
8105 * - a flattened component name that matched an existing service was specified as the
8106 * first arg: dump that one service
8107 * - the first arg isn't the flattened component name of an existing service:
8108 * dump all services whose component contains the first arg as a substring
8109 */
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008110 protected boolean dumpService(FileDescriptor fd, PrintWriter pw, String name, String[] args,
8111 int opti, boolean dumpAll) {
8112 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008113
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008114 if ("all".equals(name)) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07008115 synchronized (this) {
8116 for (ServiceRecord r1 : mServices.values()) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008117 services.add(r1);
8118 }
8119 }
8120 } else {
8121 ComponentName componentName = name != null
8122 ? ComponentName.unflattenFromString(name) : null;
8123 int objectId = 0;
8124 if (componentName == null) {
8125 // Not a '/' separated full component name; maybe an object ID?
8126 try {
8127 objectId = Integer.parseInt(name, 16);
8128 name = null;
8129 componentName = null;
8130 } catch (RuntimeException e) {
8131 }
8132 }
8133
8134 synchronized (this) {
8135 for (ServiceRecord r1 : mServices.values()) {
8136 if (componentName != null) {
8137 if (r1.name.equals(componentName)) {
8138 services.add(r1);
8139 }
8140 } else if (name != null) {
8141 if (r1.name.flattenToString().contains(name)) {
8142 services.add(r1);
8143 }
8144 } else if (System.identityHashCode(r1) == objectId) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07008145 services.add(r1);
8146 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008147 }
8148 }
8149 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008150
8151 if (services.size() <= 0) {
8152 return false;
8153 }
8154
8155 boolean needSep = false;
8156 for (int i=0; i<services.size(); i++) {
8157 if (needSep) {
8158 pw.println();
8159 }
8160 needSep = true;
8161 dumpService("", fd, pw, services.get(i), args, dumpAll);
8162 }
8163 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008164 }
8165
8166 /**
8167 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
8168 * there is a thread associated with the service.
8169 */
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008170 private void dumpService(String prefix, FileDescriptor fd, PrintWriter pw,
8171 final ServiceRecord r, String[] args, boolean dumpAll) {
8172 String innerPrefix = prefix + " ";
8173 synchronized (this) {
8174 pw.print(prefix); pw.print("SERVICE ");
8175 pw.print(r.shortName); pw.print(" ");
8176 pw.print(Integer.toHexString(System.identityHashCode(r)));
8177 pw.print(" pid=");
8178 if (r.app != null) pw.println(r.app.pid);
8179 else pw.println("(not running)");
8180 if (dumpAll) {
8181 r.dump(pw, innerPrefix);
8182 }
8183 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008184 if (r.app != null && r.app.thread != null) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008185 pw.print(prefix); pw.println(" Client:");
8186 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008187 try {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008188 TransferPipe tp = new TransferPipe();
8189 try {
8190 r.app.thread.dumpService(tp.getWriteFd().getFileDescriptor(), r, args);
8191 tp.setBufferPrefix(prefix + " ");
8192 tp.go(fd);
8193 } finally {
8194 tp.kill();
8195 }
8196 } catch (IOException e) {
8197 pw.println(prefix + " Failure while dumping the service: " + e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008198 } catch (RemoteException e) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008199 pw.println(prefix + " Got a RemoteException while dumping the service");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008200 }
8201 }
8202 }
8203
Dianne Hackborn625ac272010-09-17 18:29:22 -07008204 /**
8205 * There are three things that cmd can be:
8206 * - a flattened component name that matched an existing activity
8207 * - the cmd arg isn't the flattened component name of an existing activity:
8208 * dump all activity whose component contains the cmd as a substring
8209 * - A hex number of the ActivityRecord object instance.
8210 */
8211 protected boolean dumpActivity(FileDescriptor fd, PrintWriter pw, String name, String[] args,
8212 int opti, boolean dumpAll) {
Dianne Hackborn625ac272010-09-17 18:29:22 -07008213 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008214
8215 if ("all".equals(name)) {
8216 synchronized (this) {
8217 for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
Dianne Hackborn625ac272010-09-17 18:29:22 -07008218 activities.add(r1);
8219 }
8220 }
Dianne Hackbornf9302322011-06-14 18:36:14 -07008221 } else if ("top".equals(name)) {
8222 synchronized (this) {
8223 final int N = mMainStack.mHistory.size();
8224 if (N > 0) {
8225 activities.add((ActivityRecord)mMainStack.mHistory.get(N-1));
8226 }
8227 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008228 } else {
8229 ComponentName componentName = ComponentName.unflattenFromString(name);
8230 int objectId = 0;
8231 if (componentName == null) {
8232 // Not a '/' separated full component name; maybe an object ID?
8233 try {
8234 objectId = Integer.parseInt(name, 16);
8235 name = null;
8236 componentName = null;
8237 } catch (RuntimeException e) {
8238 }
8239 }
8240
8241 synchronized (this) {
8242 for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
8243 if (componentName != null) {
8244 if (r1.intent.getComponent().equals(componentName)) {
8245 activities.add(r1);
8246 }
8247 } else if (name != null) {
8248 if (r1.intent.getComponent().flattenToString().contains(name)) {
8249 activities.add(r1);
8250 }
8251 } else if (System.identityHashCode(r1) == objectId) {
8252 activities.add(r1);
8253 }
8254 }
8255 }
Dianne Hackborn625ac272010-09-17 18:29:22 -07008256 }
8257
8258 if (activities.size() <= 0) {
8259 return false;
8260 }
8261
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008262 String[] newArgs = new String[args.length - opti];
8263 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
8264
Dianne Hackborn30d71892010-12-11 10:37:55 -08008265 TaskRecord lastTask = null;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008266 boolean needSep = false;
Dianne Hackborn30d71892010-12-11 10:37:55 -08008267 for (int i=activities.size()-1; i>=0; i--) {
8268 ActivityRecord r = (ActivityRecord)activities.get(i);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008269 if (needSep) {
8270 pw.println();
8271 }
8272 needSep = true;
8273 synchronized (this) {
8274 if (lastTask != r.task) {
8275 lastTask = r.task;
8276 pw.print("TASK "); pw.print(lastTask.affinity);
8277 pw.print(" id="); pw.println(lastTask.taskId);
8278 if (dumpAll) {
8279 lastTask.dump(pw, " ");
8280 }
Dianne Hackborn30d71892010-12-11 10:37:55 -08008281 }
8282 }
8283 dumpActivity(" ", fd, pw, activities.get(i), newArgs, dumpAll);
Dianne Hackborn625ac272010-09-17 18:29:22 -07008284 }
8285 return true;
8286 }
8287
8288 /**
8289 * Invokes IApplicationThread.dumpActivity() on the thread of the specified activity if
8290 * there is a thread associated with the activity.
8291 */
Dianne Hackborn30d71892010-12-11 10:37:55 -08008292 private void dumpActivity(String prefix, FileDescriptor fd, PrintWriter pw,
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008293 final ActivityRecord r, String[] args, boolean dumpAll) {
8294 String innerPrefix = prefix + " ";
Dianne Hackborn30d71892010-12-11 10:37:55 -08008295 synchronized (this) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008296 pw.print(prefix); pw.print("ACTIVITY "); pw.print(r.shortComponentName);
8297 pw.print(" "); pw.print(Integer.toHexString(System.identityHashCode(r)));
8298 pw.print(" pid=");
Dianne Hackborn30d71892010-12-11 10:37:55 -08008299 if (r.app != null) pw.println(r.app.pid);
8300 else pw.println("(not running)");
8301 if (dumpAll) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008302 r.dump(pw, innerPrefix);
Dianne Hackborn625ac272010-09-17 18:29:22 -07008303 }
Dianne Hackborn625ac272010-09-17 18:29:22 -07008304 }
8305 if (r.app != null && r.app.thread != null) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008306 // flush anything that is already in the PrintWriter since the thread is going
8307 // to write to the file descriptor directly
8308 pw.flush();
Dianne Hackborn625ac272010-09-17 18:29:22 -07008309 try {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008310 TransferPipe tp = new TransferPipe();
8311 try {
8312 r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(), r,
8313 innerPrefix, args);
8314 tp.go(fd);
8315 } finally {
8316 tp.kill();
8317 }
8318 } catch (IOException e) {
8319 pw.println(innerPrefix + "Failure while dumping the activity: " + e);
Dianne Hackborn625ac272010-09-17 18:29:22 -07008320 } catch (RemoteException e) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008321 pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
Dianne Hackborn625ac272010-09-17 18:29:22 -07008322 }
8323 }
8324 }
8325
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008326 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8327 int opti, boolean dumpAll) {
8328 boolean needSep = false;
8329
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008330 pw.println("ACTIVITY MANAGER BROADCAST STATE (dumpsys activity broadcasts)");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008331 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008332 if (mRegisteredReceivers.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008333 pw.println(" Registered Receivers:");
8334 Iterator it = mRegisteredReceivers.values().iterator();
8335 while (it.hasNext()) {
8336 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008337 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008338 r.dump(pw, " ");
8339 }
8340 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008341
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008342 pw.println();
8343 pw.println(" Receiver Resolver Table:");
8344 mReceiverResolver.dump(pw, null, " ", null, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008345 needSep = true;
8346 }
8347
8348 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
8349 || mPendingBroadcast != null) {
8350 if (mParallelBroadcasts.size() > 0) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008351 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008352 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008353 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008354 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
8355 pw.println(" Broadcast #" + i + ":");
8356 mParallelBroadcasts.get(i).dump(pw, " ");
8357 }
8358 if (mOrderedBroadcasts.size() > 0) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008359 pw.println();
Dianne Hackborn399cccb2010-04-13 22:57:49 -07008360 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008361 }
8362 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
8363 pw.println(" Serialized Broadcast #" + i + ":");
8364 mOrderedBroadcasts.get(i).dump(pw, " ");
8365 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008366 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008367 pw.println(" Pending broadcast:");
8368 if (mPendingBroadcast != null) {
8369 mPendingBroadcast.dump(pw, " ");
8370 } else {
8371 pw.println(" (null)");
8372 }
8373 needSep = true;
8374 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008375
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008376 if (needSep) {
8377 pw.println();
8378 }
8379 pw.println(" Historical broadcasts:");
8380 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
8381 BroadcastRecord r = mBroadcastHistory[i];
8382 if (r == null) {
8383 break;
8384 }
8385 if (dumpAll) {
8386 pw.print(" Historical Broadcast #"); pw.print(i); pw.println(":");
8387 r.dump(pw, " ");
8388 } else {
8389 if (i >= 50) {
8390 pw.println(" ...");
Dianne Hackborn12527f92009-11-11 17:39:50 -08008391 break;
8392 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008393 pw.print(" #"); pw.print(i); pw.print(": "); pw.println(r);
Dianne Hackborn12527f92009-11-11 17:39:50 -08008394 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008395 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008396 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008397
8398 if (mStickyBroadcasts != null) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008399 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008400 pw.println(" Sticky broadcasts:");
8401 StringBuilder sb = new StringBuilder(128);
8402 for (Map.Entry<String, ArrayList<Intent>> ent
8403 : mStickyBroadcasts.entrySet()) {
8404 pw.print(" * Sticky action "); pw.print(ent.getKey());
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008405 if (dumpAll) {
8406 pw.println(":");
8407 ArrayList<Intent> intents = ent.getValue();
8408 final int N = intents.size();
8409 for (int i=0; i<N; i++) {
8410 sb.setLength(0);
8411 sb.append(" Intent: ");
8412 intents.get(i).toShortString(sb, true, false);
8413 pw.println(sb.toString());
8414 Bundle bundle = intents.get(i).getExtras();
8415 if (bundle != null) {
8416 pw.print(" ");
8417 pw.println(bundle.toString());
8418 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008419 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008420 } else {
8421 pw.println("");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008422 }
8423 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008424 needSep = true;
8425 }
8426
8427 if (dumpAll) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008428 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008429 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008430 pw.println(" mHandler:");
8431 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008432 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008433 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008434
8435 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008436 }
8437
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008438 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008439 int opti, boolean dumpAll, boolean dumpClient) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008440 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008441
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008442 pw.println("ACTIVITY MANAGER SERVICES (dumpsys activity services)");
8443 if (mServices.size() > 0) {
8444 pw.println(" Active services:");
8445 long nowReal = SystemClock.elapsedRealtime();
8446 Iterator<ServiceRecord> it = mServices.values().iterator();
8447 needSep = false;
8448 while (it.hasNext()) {
8449 ServiceRecord r = it.next();
8450 if (needSep) {
8451 pw.println();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008452 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008453 pw.print(" * "); pw.println(r);
8454 if (dumpAll) {
8455 r.dump(pw, " ");
8456 needSep = true;
8457 } else {
8458 pw.print(" app="); pw.println(r.app);
8459 pw.print(" created=");
8460 TimeUtils.formatDuration(r.createTime, nowReal, pw);
8461 pw.print(" started="); pw.print(r.startRequested);
8462 pw.print(" connections="); pw.println(r.connections.size());
8463 }
8464 if (dumpClient && r.app != null && r.app.thread != null) {
8465 pw.println(" Client:");
8466 pw.flush();
8467 try {
8468 TransferPipe tp = new TransferPipe();
8469 try {
8470 r.app.thread.dumpService(
8471 tp.getWriteFd().getFileDescriptor(), r, args);
8472 tp.setBufferPrefix(" ");
8473 // Short timeout, since blocking here can
8474 // deadlock with the application.
8475 tp.go(fd, 2000);
8476 } finally {
8477 tp.kill();
8478 }
8479 } catch (IOException e) {
8480 pw.println(" Failure while dumping the service: " + e);
8481 } catch (RemoteException e) {
8482 pw.println(" Got a RemoteException while dumping the service");
8483 }
8484 needSep = true;
8485 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008486 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008487 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008488 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008489
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008490 if (mPendingServices.size() > 0) {
8491 if (needSep) pw.println(" ");
8492 pw.println(" Pending services:");
8493 for (int i=0; i<mPendingServices.size(); i++) {
8494 ServiceRecord r = mPendingServices.get(i);
8495 pw.print(" * Pending "); 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 (mRestartingServices.size() > 0) {
8502 if (needSep) pw.println(" ");
8503 pw.println(" Restarting services:");
8504 for (int i=0; i<mRestartingServices.size(); i++) {
8505 ServiceRecord r = mRestartingServices.get(i);
8506 pw.print(" * Restarting "); pw.println(r);
8507 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008508 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008509 needSep = true;
8510 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008511
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008512 if (mStoppingServices.size() > 0) {
8513 if (needSep) pw.println(" ");
8514 pw.println(" Stopping services:");
8515 for (int i=0; i<mStoppingServices.size(); i++) {
8516 ServiceRecord r = mStoppingServices.get(i);
8517 pw.print(" * Stopping "); pw.println(r);
8518 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008519 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008520 needSep = true;
8521 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008522
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008523 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008524 if (mServiceConnections.size() > 0) {
8525 if (needSep) pw.println(" ");
8526 pw.println(" Connection bindings to services:");
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008527 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008528 = mServiceConnections.values().iterator();
8529 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008530 ArrayList<ConnectionRecord> r = it.next();
8531 for (int i=0; i<r.size(); i++) {
8532 pw.print(" * "); pw.println(r.get(i));
8533 r.get(i).dump(pw, " ");
8534 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008535 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008536 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008537 }
8538 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008539
8540 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008541 }
8542
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008543 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8544 int opti, boolean dumpAll) {
8545 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008546
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008547 pw.println("ACTIVITY MANAGER CONTENT PROVIDERS (dumpsys activity providers)");
8548 if (mProvidersByClass.size() > 0) {
8549 if (needSep) pw.println(" ");
8550 pw.println(" Published content providers (by class):");
8551 Iterator<Map.Entry<String, ContentProviderRecord>> it
8552 = mProvidersByClass.entrySet().iterator();
8553 while (it.hasNext()) {
8554 Map.Entry<String, ContentProviderRecord> e = it.next();
8555 ContentProviderRecord r = e.getValue();
8556 if (dumpAll) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008557 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008558 r.dump(pw, " ");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008559 } else {
8560 pw.print(" * "); pw.print(r.name.toShortString());
8561 if (r.app != null) {
8562 pw.println(":");
8563 pw.print(" "); pw.println(r.app);
8564 } else {
8565 pw.println();
8566 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008567 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008568 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008569 needSep = true;
8570 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008571
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008572 if (dumpAll) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008573 if (mProvidersByName.size() > 0) {
8574 pw.println(" ");
8575 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -07008576 Iterator<Map.Entry<String, ContentProviderRecord>> it
8577 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008578 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008579 Map.Entry<String, ContentProviderRecord> e = it.next();
8580 ContentProviderRecord r = e.getValue();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008581 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
8582 pw.println(r);
8583 }
8584 needSep = true;
8585 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008586 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008587
8588 if (mLaunchingProviders.size() > 0) {
8589 if (needSep) pw.println(" ");
8590 pw.println(" Launching content providers:");
8591 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
8592 pw.print(" Launching #"); pw.print(i); pw.print(": ");
8593 pw.println(mLaunchingProviders.get(i));
8594 }
8595 needSep = true;
8596 }
8597
8598 if (mGrantedUriPermissions.size() > 0) {
8599 pw.println();
8600 pw.println("Granted Uri Permissions:");
8601 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
8602 int uid = mGrantedUriPermissions.keyAt(i);
8603 HashMap<Uri, UriPermission> perms
8604 = mGrantedUriPermissions.valueAt(i);
8605 pw.print(" * UID "); pw.print(uid);
8606 pw.println(" holds:");
8607 for (UriPermission perm : perms.values()) {
8608 pw.print(" "); pw.println(perm);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008609 if (dumpAll) {
8610 perm.dump(pw, " ");
8611 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008612 }
8613 }
8614 needSep = true;
8615 }
8616
8617 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008618 }
8619
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008620 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8621 int opti, boolean dumpAll) {
8622 boolean needSep = false;
8623
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008624 if (this.mIntentSenderRecords.size() > 0) {
8625 pw.println("ACTIVITY MANAGER PENDING INTENTS (dumpsys activity intents)");
8626 Iterator<WeakReference<PendingIntentRecord>> it
8627 = mIntentSenderRecords.values().iterator();
8628 while (it.hasNext()) {
8629 WeakReference<PendingIntentRecord> ref = it.next();
8630 PendingIntentRecord rec = ref != null ? ref.get(): null;
8631 needSep = true;
8632 if (rec != null) {
8633 pw.print(" * "); pw.println(rec);
8634 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008635 rec.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008636 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008637 } else {
8638 pw.print(" * "); pw.println(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008639 }
8640 }
8641 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008642
8643 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008644 }
8645
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008646 private static final void dumpHistoryList(FileDescriptor fd, PrintWriter pw, List list,
8647 String prefix, String label, boolean complete, boolean brief, boolean client) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008648 TaskRecord lastTask = null;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008649 boolean needNL = false;
8650 final String innerPrefix = prefix + " ";
8651 final String[] args = new String[0];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008652 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008653 final ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackbornf26fd992011-04-08 18:14:09 -07008654 final boolean full = !brief && (complete || !r.isInHistory());
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008655 if (needNL) {
8656 pw.println(" ");
8657 needNL = false;
8658 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008659 if (lastTask != r.task) {
8660 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008661 pw.print(prefix);
8662 pw.print(full ? "* " : " ");
8663 pw.println(lastTask);
8664 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008665 lastTask.dump(pw, prefix + " ");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008666 } else if (complete) {
8667 // Complete + brief == give a summary. Isn't that obvious?!?
8668 if (lastTask.intent != null) {
8669 pw.print(prefix); pw.print(" "); pw.println(lastTask.intent);
8670 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008671 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008672 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008673 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
8674 pw.print(" #"); pw.print(i); pw.print(": ");
8675 pw.println(r);
8676 if (full) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008677 r.dump(pw, innerPrefix);
8678 } else if (complete) {
8679 // Complete + brief == give a summary. Isn't that obvious?!?
8680 pw.print(innerPrefix); pw.println(r.intent);
8681 if (r.app != null) {
8682 pw.print(innerPrefix); pw.println(r.app);
8683 }
8684 }
8685 if (client && r.app != null && r.app.thread != null) {
8686 // flush anything that is already in the PrintWriter since the thread is going
8687 // to write to the file descriptor directly
8688 pw.flush();
8689 try {
8690 TransferPipe tp = new TransferPipe();
8691 try {
8692 r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(), r,
8693 innerPrefix, args);
8694 // Short timeout, since blocking here can
8695 // deadlock with the application.
8696 tp.go(fd, 2000);
8697 } finally {
8698 tp.kill();
8699 }
8700 } catch (IOException e) {
8701 pw.println(innerPrefix + "Failure while dumping the activity: " + e);
8702 } catch (RemoteException e) {
8703 pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
8704 }
8705 needNL = true;
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008706 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008707 }
8708 }
8709
Dianne Hackborn09c916b2009-12-08 14:50:51 -08008710 private static String buildOomTag(String prefix, String space, int val, int base) {
8711 if (val == base) {
8712 if (space == null) return prefix;
8713 return prefix + " ";
8714 }
8715 return prefix + "+" + Integer.toString(val-base);
8716 }
8717
8718 private static final int dumpProcessList(PrintWriter pw,
8719 ActivityManagerService service, List list,
Dianne Hackborn287952c2010-09-22 22:34:31 -07008720 String prefix, String normalLabel, String persistentLabel) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008721 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07008722 final int N = list.size()-1;
8723 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008724 ProcessRecord r = (ProcessRecord)list.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008725 pw.println(String.format("%s%s #%2d: %s",
8726 prefix, (r.persistent ? persistentLabel : normalLabel),
8727 i, r.toString()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008728 if (r.persistent) {
8729 numPers++;
8730 }
8731 }
8732 return numPers;
8733 }
8734
Dianne Hackborn287952c2010-09-22 22:34:31 -07008735 private static final void dumpProcessOomList(PrintWriter pw,
8736 ActivityManagerService service, List<ProcessRecord> list,
8737 String prefix, String normalLabel, String persistentLabel,
8738 boolean inclDetails) {
8739
8740 final long curRealtime = SystemClock.elapsedRealtime();
8741 final long realtimeSince = curRealtime - service.mLastPowerCheckRealtime;
8742 final long curUptime = SystemClock.uptimeMillis();
8743 final long uptimeSince = curUptime - service.mLastPowerCheckUptime;
8744
8745 final int N = list.size()-1;
8746 for (int i=N; i>=0; i--) {
8747 ProcessRecord r = list.get(i);
8748 String oomAdj;
8749 if (r.setAdj >= EMPTY_APP_ADJ) {
8750 oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
8751 } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
8752 oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
8753 } else if (r.setAdj >= HOME_APP_ADJ) {
8754 oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
8755 } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
8756 oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
8757 } else if (r.setAdj >= BACKUP_APP_ADJ) {
8758 oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
8759 } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
8760 oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
8761 } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
8762 oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
8763 } else if (r.setAdj >= VISIBLE_APP_ADJ) {
8764 oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
8765 } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
8766 oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
8767 } else if (r.setAdj >= CORE_SERVER_ADJ) {
8768 oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
8769 } else if (r.setAdj >= SYSTEM_ADJ) {
8770 oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
8771 } else {
8772 oomAdj = Integer.toString(r.setAdj);
8773 }
8774 String schedGroup;
8775 switch (r.setSchedGroup) {
8776 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
8777 schedGroup = "B";
8778 break;
8779 case Process.THREAD_GROUP_DEFAULT:
8780 schedGroup = "F";
8781 break;
8782 default:
8783 schedGroup = Integer.toString(r.setSchedGroup);
8784 break;
8785 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07008786 String foreground;
8787 if (r.foregroundActivities) {
8788 foreground = "A";
8789 } else if (r.foregroundServices) {
8790 foreground = "S";
8791 } else {
8792 foreground = " ";
8793 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -07008794 pw.println(String.format("%s%s #%2d: adj=%s/%s%s trm=%2d %s (%s)",
Dianne Hackborn287952c2010-09-22 22:34:31 -07008795 prefix, (r.persistent ? persistentLabel : normalLabel),
Dianne Hackbornce86ba82011-07-13 19:33:41 -07008796 N-i, oomAdj, schedGroup, foreground, r.trimMemoryLevel,
8797 r.toShortString(), r.adjType));
Dianne Hackborn287952c2010-09-22 22:34:31 -07008798 if (r.adjSource != null || r.adjTarget != null) {
8799 pw.print(prefix);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008800 pw.print(" ");
Dianne Hackborn287952c2010-09-22 22:34:31 -07008801 if (r.adjTarget instanceof ComponentName) {
8802 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
8803 } else if (r.adjTarget != null) {
8804 pw.print(r.adjTarget.toString());
8805 } else {
8806 pw.print("{null}");
8807 }
8808 pw.print("<=");
8809 if (r.adjSource instanceof ProcessRecord) {
8810 pw.print("Proc{");
8811 pw.print(((ProcessRecord)r.adjSource).toShortString());
8812 pw.println("}");
8813 } else if (r.adjSource != null) {
8814 pw.println(r.adjSource.toString());
8815 } else {
8816 pw.println("{null}");
8817 }
8818 }
8819 if (inclDetails) {
8820 pw.print(prefix);
8821 pw.print(" ");
8822 pw.print("oom: max="); pw.print(r.maxAdj);
8823 pw.print(" hidden="); pw.print(r.hiddenAdj);
8824 pw.print(" curRaw="); pw.print(r.curRawAdj);
8825 pw.print(" setRaw="); pw.print(r.setRawAdj);
8826 pw.print(" cur="); pw.print(r.curAdj);
8827 pw.print(" set="); pw.println(r.setAdj);
8828 pw.print(prefix);
8829 pw.print(" ");
8830 pw.print("keeping="); pw.print(r.keeping);
8831 pw.print(" hidden="); pw.print(r.hidden);
Dianne Hackbornc68c9132011-07-29 01:25:18 -07008832 pw.print(" empty="); pw.print(r.empty);
8833 pw.print(" hasAboveClient="); pw.println(r.hasAboveClient);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008834
8835 if (!r.keeping) {
8836 if (r.lastWakeTime != 0) {
8837 long wtime;
8838 BatteryStatsImpl stats = service.mBatteryStatsService.getActiveStatistics();
8839 synchronized (stats) {
8840 wtime = stats.getProcessWakeTime(r.info.uid,
8841 r.pid, curRealtime);
8842 }
8843 long timeUsed = wtime - r.lastWakeTime;
8844 pw.print(prefix);
8845 pw.print(" ");
8846 pw.print("keep awake over ");
8847 TimeUtils.formatDuration(realtimeSince, pw);
8848 pw.print(" used ");
8849 TimeUtils.formatDuration(timeUsed, pw);
8850 pw.print(" (");
8851 pw.print((timeUsed*100)/realtimeSince);
8852 pw.println("%)");
8853 }
8854 if (r.lastCpuTime != 0) {
8855 long timeUsed = r.curCpuTime - r.lastCpuTime;
8856 pw.print(prefix);
8857 pw.print(" ");
8858 pw.print("run cpu over ");
8859 TimeUtils.formatDuration(uptimeSince, pw);
8860 pw.print(" used ");
8861 TimeUtils.formatDuration(timeUsed, pw);
8862 pw.print(" (");
8863 pw.print((timeUsed*100)/uptimeSince);
8864 pw.println("%)");
8865 }
8866 }
8867 }
8868 }
8869 }
8870
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008871 ArrayList<ProcessRecord> collectProcesses(PrintWriter pw, String[] args) {
8872 ArrayList<ProcessRecord> procs;
8873 synchronized (this) {
8874 if (args != null && args.length > 0
8875 && args[0].charAt(0) != '-') {
8876 procs = new ArrayList<ProcessRecord>();
8877 int pid = -1;
8878 try {
8879 pid = Integer.parseInt(args[0]);
8880 } catch (NumberFormatException e) {
8881
8882 }
8883 for (int i=mLruProcesses.size()-1; i>=0; i--) {
8884 ProcessRecord proc = mLruProcesses.get(i);
8885 if (proc.pid == pid) {
8886 procs.add(proc);
8887 } else if (proc.processName.equals(args[0])) {
8888 procs.add(proc);
8889 }
8890 }
8891 if (procs.size() <= 0) {
8892 pw.println("No process found for: " + args[0]);
8893 return null;
8894 }
8895 } else {
8896 procs = new ArrayList<ProcessRecord>(mLruProcesses);
8897 }
8898 }
8899 return procs;
8900 }
8901
8902 final void dumpGraphicsHardwareUsage(FileDescriptor fd,
8903 PrintWriter pw, String[] args) {
8904 ArrayList<ProcessRecord> procs = collectProcesses(pw, args);
8905 if (procs == null) {
8906 return;
8907 }
8908
8909 long uptime = SystemClock.uptimeMillis();
8910 long realtime = SystemClock.elapsedRealtime();
8911 pw.println("Applications Graphics Acceleration Info:");
8912 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
8913
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008914 for (int i = procs.size() - 1 ; i >= 0 ; i--) {
8915 ProcessRecord r = procs.get(i);
Chet Haase9c1e23b2011-03-24 10:51:31 -07008916 if (r.thread != null) {
8917 pw.println("\n** Graphics info for pid " + r.pid + " [" + r.processName + "] **");
8918 pw.flush();
8919 try {
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07008920 TransferPipe tp = new TransferPipe();
8921 try {
8922 r.thread.dumpGfxInfo(tp.getWriteFd().getFileDescriptor(), args);
8923 tp.go(fd);
8924 } finally {
8925 tp.kill();
8926 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008927 } catch (IOException e) {
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07008928 pw.println("Failure while dumping the app: " + r);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008929 pw.flush();
Chet Haase9c1e23b2011-03-24 10:51:31 -07008930 } catch (RemoteException e) {
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07008931 pw.println("Got a RemoteException while dumping the app " + r);
Chet Haase9c1e23b2011-03-24 10:51:31 -07008932 pw.flush();
8933 }
8934 }
8935 }
Chet Haase9c1e23b2011-03-24 10:51:31 -07008936 }
8937
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07008938 final static class MemItem {
8939 final String label;
8940 final long pss;
8941
8942 public MemItem(String _label, long _pss) {
8943 label = _label;
8944 pss = _pss;
8945 }
8946 }
8947
8948 final void dumpMemItems(PrintWriter pw, String prefix, ArrayList<MemItem> items) {
8949 Collections.sort(items, new Comparator<MemItem>() {
8950 @Override
8951 public int compare(MemItem lhs, MemItem rhs) {
8952 if (lhs.pss < rhs.pss) {
8953 return 1;
8954 } else if (lhs.pss > rhs.pss) {
8955 return -1;
8956 }
8957 return 0;
8958 }
8959 });
8960
8961 for (int i=0; i<items.size(); i++) {
8962 MemItem mi = items.get(i);
8963 pw.print(prefix); pw.printf("%8d Kb: ", mi.pss); pw.println(mi.label);
8964 }
8965 }
8966
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008967 final void dumpApplicationMemoryUsage(FileDescriptor fd,
8968 PrintWriter pw, String prefix, String[] args) {
8969 ArrayList<ProcessRecord> procs = collectProcesses(pw, args);
8970 if (procs == null) {
8971 return;
8972 }
8973
Dianne Hackborn6447ca32009-04-07 19:50:08 -07008974 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008975 long uptime = SystemClock.uptimeMillis();
8976 long realtime = SystemClock.elapsedRealtime();
8977
8978 if (isCheckinRequest) {
8979 // short checkin version
8980 pw.println(uptime + "," + realtime);
8981 pw.flush();
8982 } else {
8983 pw.println("Applications Memory Usage (kB):");
8984 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
8985 }
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07008986
8987 ArrayList<MemItem> procMems = new ArrayList<MemItem>();
8988 long nativePss=0, dalvikPss=0, otherPss=0;
8989 long[] miscPss = new long[Debug.MemoryInfo.NUM_OTHER_STATS];
8990
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008991 for (int i = procs.size() - 1 ; i >= 0 ; i--) {
8992 ProcessRecord r = procs.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008993 if (r.thread != null) {
8994 if (!isCheckinRequest) {
8995 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
8996 pw.flush();
8997 }
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07008998 Debug.MemoryInfo mi = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008999 try {
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009000 mi = r.thread.dumpMemInfo(fd, args);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009001 } catch (RemoteException e) {
9002 if (!isCheckinRequest) {
9003 pw.println("Got RemoteException!");
9004 pw.flush();
9005 }
9006 }
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009007 if (!isCheckinRequest && mi != null) {
9008 procMems.add(new MemItem(r.processName + " (pid " + r.pid + ")",
9009 mi.getTotalPss()));
9010
9011 nativePss += mi.nativePss;
9012 dalvikPss += mi.dalvikPss;
9013 otherPss += mi.otherPss;
9014 for (int j=0; j<Debug.MemoryInfo.NUM_OTHER_STATS; j++) {
9015 long mem = mi.getOtherPss(j);
9016 miscPss[j] += mem;
9017 otherPss -= mem;
9018 }
9019 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009020 }
9021 }
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009022
9023 if (!isCheckinRequest && procs.size() > 1) {
9024 ArrayList<MemItem> catMems = new ArrayList<MemItem>();
9025
9026 catMems.add(new MemItem("Native", nativePss));
9027 catMems.add(new MemItem("Dalvik", dalvikPss));
9028 catMems.add(new MemItem("Unknown", otherPss));
9029 for (int j=0; j<Debug.MemoryInfo.NUM_OTHER_STATS; j++) {
9030 catMems.add(new MemItem(Debug.MemoryInfo.getOtherLabel(j), miscPss[j]));
9031 }
9032
9033 pw.println();
9034 pw.println("Total PSS by process:");
9035 dumpMemItems(pw, " ", procMems);
9036 pw.println();
9037 pw.println("Total PSS by category:");
9038 dumpMemItems(pw, " ", catMems);
9039 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009040 }
9041
9042 /**
9043 * Searches array of arguments for the specified string
9044 * @param args array of argument strings
9045 * @param value value to search for
9046 * @return true if the value is contained in the array
9047 */
9048 private static boolean scanArgs(String[] args, String value) {
9049 if (args != null) {
9050 for (String arg : args) {
9051 if (value.equals(arg)) {
9052 return true;
9053 }
9054 }
9055 }
9056 return false;
9057 }
9058
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009059 private final void killServicesLocked(ProcessRecord app,
9060 boolean allowRestart) {
9061 // Report disconnected services.
9062 if (false) {
9063 // XXX we are letting the client link to the service for
9064 // death notifications.
9065 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009066 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009067 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009068 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009069 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009070 Iterator<ArrayList<ConnectionRecord>> jt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009071 = r.connections.values().iterator();
9072 while (jt.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009073 ArrayList<ConnectionRecord> cl = jt.next();
9074 for (int i=0; i<cl.size(); i++) {
9075 ConnectionRecord c = cl.get(i);
9076 if (c.binding.client != app) {
9077 try {
9078 //c.conn.connected(r.className, null);
9079 } catch (Exception e) {
9080 // todo: this should be asynchronous!
9081 Slog.w(TAG, "Exception thrown disconnected servce "
9082 + r.shortName
9083 + " from app " + app.processName, e);
9084 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009085 }
9086 }
9087 }
9088 }
9089 }
9090 }
9091 }
9092
9093 // Clean up any connections this application has to other services.
9094 if (app.connections.size() > 0) {
9095 Iterator<ConnectionRecord> it = app.connections.iterator();
9096 while (it.hasNext()) {
9097 ConnectionRecord r = it.next();
9098 removeConnectionLocked(r, app, null);
9099 }
9100 }
9101 app.connections.clear();
9102
9103 if (app.services.size() != 0) {
9104 // Any services running in the application need to be placed
9105 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07009106 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009107 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009108 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009109 synchronized (sr.stats.getBatteryStats()) {
9110 sr.stats.stopLaunchedLocked();
9111 }
9112 sr.app = null;
9113 sr.executeNesting = 0;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009114 if (mStoppingServices.remove(sr)) {
9115 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
9116 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009117
9118 boolean hasClients = sr.bindings.size() > 0;
9119 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009120 Iterator<IntentBindRecord> bindings
9121 = sr.bindings.values().iterator();
9122 while (bindings.hasNext()) {
9123 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009124 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009125 + ": shouldUnbind=" + b.hasBound);
9126 b.binder = null;
9127 b.requested = b.received = b.hasBound = false;
9128 }
9129 }
9130
Dianne Hackborn070783f2010-12-29 16:46:28 -08009131 if (sr.crashCount >= 2 && (sr.serviceInfo.applicationInfo.flags
9132 &ApplicationInfo.FLAG_PERSISTENT) == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009133 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009134 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009135 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009136 sr.crashCount, sr.shortName, app.pid);
9137 bringDownServiceLocked(sr, true);
9138 } else if (!allowRestart) {
9139 bringDownServiceLocked(sr, true);
9140 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009141 boolean canceled = scheduleServiceRestartLocked(sr, true);
9142
9143 // Should the service remain running? Note that in the
9144 // extreme case of so many attempts to deliver a command
Dianne Hackborn130b0d22011-07-26 22:07:48 -07009145 // that it failed we also will stop it here.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009146 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
9147 if (sr.pendingStarts.size() == 0) {
9148 sr.startRequested = false;
9149 if (!hasClients) {
9150 // Whoops, no reason to restart!
9151 bringDownServiceLocked(sr, true);
9152 }
9153 }
9154 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009155 }
9156 }
9157
9158 if (!allowRestart) {
9159 app.services.clear();
9160 }
9161 }
9162
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009163 // Make sure we have no more records on the stopping list.
9164 int i = mStoppingServices.size();
9165 while (i > 0) {
9166 i--;
9167 ServiceRecord sr = mStoppingServices.get(i);
9168 if (sr.app == app) {
9169 mStoppingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009170 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009171 }
9172 }
9173
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009174 app.executingServices.clear();
9175 }
9176
9177 private final void removeDyingProviderLocked(ProcessRecord proc,
9178 ContentProviderRecord cpr) {
9179 synchronized (cpr) {
9180 cpr.launchingApp = null;
9181 cpr.notifyAll();
9182 }
9183
9184 mProvidersByClass.remove(cpr.info.name);
9185 String names[] = cpr.info.authority.split(";");
9186 for (int j = 0; j < names.length; j++) {
9187 mProvidersByName.remove(names[j]);
9188 }
9189
9190 Iterator<ProcessRecord> cit = cpr.clients.iterator();
9191 while (cit.hasNext()) {
9192 ProcessRecord capp = cit.next();
9193 if (!capp.persistent && capp.thread != null
9194 && capp.pid != 0
9195 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07009196 Slog.i(TAG, "Kill " + capp.processName
9197 + " (pid " + capp.pid + "): provider " + cpr.info.name
9198 + " in dying process " + proc.processName);
9199 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
9200 capp.processName, capp.setAdj, "dying provider " + proc.processName);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07009201 Process.killProcessQuiet(capp.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009202 }
9203 }
9204
9205 mLaunchingProviders.remove(cpr);
9206 }
9207
9208 /**
9209 * Main code for cleaning up a process when it has gone away. This is
9210 * called both as a result of the process dying, or directly when stopping
9211 * a process when running in single process mode.
9212 */
9213 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
Dianne Hackborn130b0d22011-07-26 22:07:48 -07009214 boolean restarting, boolean allowRestart, int index) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009215 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009216 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009217 }
9218
Dianne Hackborn36124872009-10-08 16:22:03 -07009219 mProcessesToGc.remove(app);
9220
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009221 // Dismiss any open dialogs.
9222 if (app.crashDialog != null) {
9223 app.crashDialog.dismiss();
9224 app.crashDialog = null;
9225 }
9226 if (app.anrDialog != null) {
9227 app.anrDialog.dismiss();
9228 app.anrDialog = null;
9229 }
9230 if (app.waitDialog != null) {
9231 app.waitDialog.dismiss();
9232 app.waitDialog = null;
9233 }
9234
9235 app.crashing = false;
9236 app.notResponding = false;
9237
9238 app.resetPackageList();
Dianne Hackborn1b64e0d2011-07-17 15:23:59 -07009239 app.unlinkDeathRecipient();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009240 app.thread = null;
9241 app.forcingToForeground = null;
9242 app.foregroundServices = false;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07009243 app.foregroundActivities = false;
Dianne Hackbornf0754f5b2011-07-21 16:02:07 -07009244 app.hasShownUi = false;
Dianne Hackbornc68c9132011-07-29 01:25:18 -07009245 app.hasAboveClient = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009246
Dianne Hackborn130b0d22011-07-26 22:07:48 -07009247 killServicesLocked(app, allowRestart);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009248
9249 boolean restart = false;
9250
9251 int NL = mLaunchingProviders.size();
9252
9253 // Remove published content providers.
9254 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009255 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009256 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009257 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009258 cpr.provider = null;
9259 cpr.app = null;
9260
9261 // See if someone is waiting for this provider... in which
9262 // case we don't remove it, but just let it restart.
9263 int i = 0;
Dianne Hackborn130b0d22011-07-26 22:07:48 -07009264 if (!app.bad && allowRestart) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009265 for (; i<NL; i++) {
9266 if (mLaunchingProviders.get(i) == cpr) {
9267 restart = true;
9268 break;
9269 }
9270 }
9271 } else {
9272 i = NL;
9273 }
9274
9275 if (i >= NL) {
9276 removeDyingProviderLocked(app, cpr);
9277 NL = mLaunchingProviders.size();
9278 }
9279 }
9280 app.pubProviders.clear();
9281 }
9282
Dianne Hackbornf670ef72009-11-16 13:59:16 -08009283 // Take care of any launching providers waiting for this process.
9284 if (checkAppInLaunchingProvidersLocked(app, false)) {
9285 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009286 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08009287
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009288 // Unregister from connected content providers.
9289 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07009290 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009291 while (it.hasNext()) {
9292 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
9293 cpr.clients.remove(app);
9294 }
9295 app.conProviders.clear();
9296 }
9297
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009298 // At this point there may be remaining entries in mLaunchingProviders
9299 // where we were the only one waiting, so they are no longer of use.
9300 // Look for these and clean up if found.
9301 // XXX Commented out for now. Trying to figure out a way to reproduce
9302 // the actual situation to identify what is actually going on.
9303 if (false) {
9304 for (int i=0; i<NL; i++) {
9305 ContentProviderRecord cpr = (ContentProviderRecord)
9306 mLaunchingProviders.get(i);
9307 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
9308 synchronized (cpr) {
9309 cpr.launchingApp = null;
9310 cpr.notifyAll();
9311 }
9312 }
9313 }
9314 }
9315
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009316 skipCurrentReceiverLocked(app);
9317
9318 // Unregister any receivers.
9319 if (app.receivers.size() > 0) {
9320 Iterator<ReceiverList> it = app.receivers.iterator();
9321 while (it.hasNext()) {
9322 removeReceiverLocked(it.next());
9323 }
9324 app.receivers.clear();
9325 }
9326
Christopher Tate181fafa2009-05-14 11:12:14 -07009327 // If the app is undergoing backup, tell the backup manager about it
9328 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009329 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -07009330 try {
9331 IBackupManager bm = IBackupManager.Stub.asInterface(
9332 ServiceManager.getService(Context.BACKUP_SERVICE));
9333 bm.agentDisconnected(app.info.packageName);
9334 } catch (RemoteException e) {
9335 // can't happen; backup manager is local
9336 }
9337 }
9338
Jeff Sharkey287bd832011-05-28 19:36:26 -07009339 mHandler.obtainMessage(DISPATCH_PROCESS_DIED, app.pid, app.info.uid, null).sendToTarget();
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07009340
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009341 // If the caller is restarting this app, then leave it in its
9342 // current lists and let the caller take care of it.
9343 if (restarting) {
9344 return;
9345 }
9346
9347 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009348 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009349 "Removing non-persistent process during cleanup: " + app);
9350 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07009351 if (mHeavyWeightProcess == app) {
9352 mHeavyWeightProcess = null;
9353 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
9354 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009355 } else if (!app.removed) {
9356 // This app is persistent, so we need to keep its record around.
9357 // If it is not already on the pending app list, add it there
9358 // and start a new process for it.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009359 if (mPersistentStartingProcesses.indexOf(app) < 0) {
9360 mPersistentStartingProcesses.add(app);
9361 restart = true;
9362 }
9363 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07009364 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
9365 "Clean-up removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009366 mProcessesOnHold.remove(app);
9367
The Android Open Source Project4df24232009-03-05 14:34:35 -08009368 if (app == mHomeProcess) {
9369 mHomeProcess = null;
9370 }
9371
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009372 if (restart) {
9373 // We have components that still need to be running in the
9374 // process, so re-launch it.
9375 mProcessNames.put(app.processName, app.info.uid, app);
9376 startProcessLocked(app, "restart", app.processName);
9377 } else if (app.pid > 0 && app.pid != MY_PID) {
9378 // Goodbye!
9379 synchronized (mPidsSelfLocked) {
9380 mPidsSelfLocked.remove(app.pid);
9381 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
9382 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009383 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009384 }
9385 }
9386
Dianne Hackbornf670ef72009-11-16 13:59:16 -08009387 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
9388 // Look through the content providers we are waiting to have launched,
9389 // and if any run in this process then either schedule a restart of
9390 // the process or kill the client waiting for it if this process has
9391 // gone bad.
9392 int NL = mLaunchingProviders.size();
9393 boolean restart = false;
9394 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009395 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08009396 if (cpr.launchingApp == app) {
9397 if (!alwaysBad && !app.bad) {
9398 restart = true;
9399 } else {
9400 removeDyingProviderLocked(app, cpr);
9401 NL = mLaunchingProviders.size();
9402 }
9403 }
9404 }
9405 return restart;
9406 }
9407
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009408 // =========================================================
9409 // SERVICES
9410 // =========================================================
9411
9412 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
9413 ActivityManager.RunningServiceInfo info =
9414 new ActivityManager.RunningServiceInfo();
9415 info.service = r.name;
9416 if (r.app != null) {
9417 info.pid = r.app.pid;
9418 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -07009419 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009420 info.process = r.processName;
9421 info.foreground = r.isForeground;
9422 info.activeSince = r.createTime;
9423 info.started = r.startRequested;
9424 info.clientCount = r.connections.size();
9425 info.crashCount = r.crashCount;
9426 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07009427 if (r.isForeground) {
9428 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
9429 }
9430 if (r.startRequested) {
9431 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
9432 }
Dan Egnor42471dd2010-01-07 17:25:22 -08009433 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -07009434 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
9435 }
9436 if (r.app != null && r.app.persistent) {
9437 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
9438 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009439
9440 for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
9441 for (int i=0; i<connl.size(); i++) {
9442 ConnectionRecord conn = connl.get(i);
9443 if (conn.clientLabel != 0) {
9444 info.clientPackage = conn.binding.client.info.packageName;
9445 info.clientLabel = conn.clientLabel;
9446 return info;
9447 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009448 }
9449 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009450 return info;
9451 }
9452
9453 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
9454 int flags) {
9455 synchronized (this) {
9456 ArrayList<ActivityManager.RunningServiceInfo> res
9457 = new ArrayList<ActivityManager.RunningServiceInfo>();
9458
9459 if (mServices.size() > 0) {
9460 Iterator<ServiceRecord> it = mServices.values().iterator();
9461 while (it.hasNext() && res.size() < maxNum) {
9462 res.add(makeRunningServiceInfoLocked(it.next()));
9463 }
9464 }
9465
9466 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
9467 ServiceRecord r = mRestartingServices.get(i);
9468 ActivityManager.RunningServiceInfo info =
9469 makeRunningServiceInfoLocked(r);
9470 info.restarting = r.nextRestartTime;
9471 res.add(info);
9472 }
9473
9474 return res;
9475 }
9476 }
9477
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009478 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
9479 synchronized (this) {
9480 ServiceRecord r = mServices.get(name);
9481 if (r != null) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009482 for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
9483 for (int i=0; i<conn.size(); i++) {
9484 if (conn.get(i).clientIntent != null) {
9485 return conn.get(i).clientIntent;
9486 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009487 }
9488 }
9489 }
9490 }
9491 return null;
9492 }
9493
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009494 private final ServiceRecord findServiceLocked(ComponentName name,
9495 IBinder token) {
9496 ServiceRecord r = mServices.get(name);
9497 return r == token ? r : null;
9498 }
9499
9500 private final class ServiceLookupResult {
9501 final ServiceRecord record;
9502 final String permission;
9503
9504 ServiceLookupResult(ServiceRecord _record, String _permission) {
9505 record = _record;
9506 permission = _permission;
9507 }
9508 };
9509
9510 private ServiceLookupResult findServiceLocked(Intent service,
9511 String resolvedType) {
9512 ServiceRecord r = null;
9513 if (service.getComponent() != null) {
9514 r = mServices.get(service.getComponent());
9515 }
9516 if (r == null) {
9517 Intent.FilterComparison filter = new Intent.FilterComparison(service);
9518 r = mServicesByIntent.get(filter);
9519 }
9520
9521 if (r == null) {
9522 try {
9523 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009524 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009525 service, resolvedType, 0);
9526 ServiceInfo sInfo =
9527 rInfo != null ? rInfo.serviceInfo : null;
9528 if (sInfo == null) {
9529 return null;
9530 }
9531
9532 ComponentName name = new ComponentName(
9533 sInfo.applicationInfo.packageName, sInfo.name);
9534 r = mServices.get(name);
9535 } catch (RemoteException ex) {
9536 // pm is in same process, this will never happen.
9537 }
9538 }
9539 if (r != null) {
9540 int callingPid = Binder.getCallingPid();
9541 int callingUid = Binder.getCallingUid();
9542 if (checkComponentPermission(r.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009543 callingPid, callingUid, r.appInfo.uid, r.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009544 != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009545 if (!r.exported) {
9546 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
9547 + " from pid=" + callingPid
9548 + ", uid=" + callingUid
9549 + " that is not exported from uid " + r.appInfo.uid);
9550 return new ServiceLookupResult(null, "not exported from uid "
9551 + r.appInfo.uid);
9552 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009553 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009554 + " from pid=" + callingPid
9555 + ", uid=" + callingUid
9556 + " requires " + r.permission);
9557 return new ServiceLookupResult(null, r.permission);
9558 }
9559 return new ServiceLookupResult(r, null);
9560 }
9561 return null;
9562 }
9563
9564 private class ServiceRestarter implements Runnable {
9565 private ServiceRecord mService;
9566
9567 void setService(ServiceRecord service) {
9568 mService = service;
9569 }
9570
9571 public void run() {
9572 synchronized(ActivityManagerService.this) {
9573 performServiceRestartLocked(mService);
9574 }
9575 }
9576 }
9577
9578 private ServiceLookupResult retrieveServiceLocked(Intent service,
9579 String resolvedType, int callingPid, int callingUid) {
9580 ServiceRecord r = null;
9581 if (service.getComponent() != null) {
9582 r = mServices.get(service.getComponent());
9583 }
9584 Intent.FilterComparison filter = new Intent.FilterComparison(service);
9585 r = mServicesByIntent.get(filter);
9586 if (r == null) {
9587 try {
9588 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009589 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -07009590 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009591 ServiceInfo sInfo =
9592 rInfo != null ? rInfo.serviceInfo : null;
9593 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009594 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009595 ": not found");
9596 return null;
9597 }
9598
9599 ComponentName name = new ComponentName(
9600 sInfo.applicationInfo.packageName, sInfo.name);
9601 r = mServices.get(name);
9602 if (r == null) {
9603 filter = new Intent.FilterComparison(service.cloneFilter());
9604 ServiceRestarter res = new ServiceRestarter();
9605 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
9606 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
9607 synchronized (stats) {
9608 ss = stats.getServiceStatsLocked(
9609 sInfo.applicationInfo.uid, sInfo.packageName,
9610 sInfo.name);
9611 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -08009612 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009613 res.setService(r);
9614 mServices.put(name, r);
9615 mServicesByIntent.put(filter, r);
9616
9617 // Make sure this component isn't in the pending list.
9618 int N = mPendingServices.size();
9619 for (int i=0; i<N; i++) {
9620 ServiceRecord pr = mPendingServices.get(i);
9621 if (pr.name.equals(name)) {
9622 mPendingServices.remove(i);
9623 i--;
9624 N--;
9625 }
9626 }
9627 }
9628 } catch (RemoteException ex) {
9629 // pm is in same process, this will never happen.
9630 }
9631 }
9632 if (r != null) {
9633 if (checkComponentPermission(r.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009634 callingPid, callingUid, r.appInfo.uid, r.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009635 != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009636 if (!r.exported) {
9637 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
9638 + " from pid=" + callingPid
9639 + ", uid=" + callingUid
9640 + " that is not exported from uid " + r.appInfo.uid);
9641 return new ServiceLookupResult(null, "not exported from uid "
9642 + r.appInfo.uid);
9643 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009644 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009645 + " from pid=" + callingPid
9646 + ", uid=" + callingUid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009647 + " requires " + r.permission);
9648 return new ServiceLookupResult(null, r.permission);
9649 }
9650 return new ServiceLookupResult(r, null);
9651 }
9652 return null;
9653 }
9654
Dianne Hackborn287952c2010-09-22 22:34:31 -07009655 private final void bumpServiceExecutingLocked(ServiceRecord r, String why) {
9656 if (DEBUG_SERVICE) Log.v(TAG, ">>> EXECUTING "
9657 + why + " of " + r + " in app " + r.app);
9658 else if (DEBUG_SERVICE_EXECUTING) Log.v(TAG, ">>> EXECUTING "
9659 + why + " of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009660 long now = SystemClock.uptimeMillis();
9661 if (r.executeNesting == 0 && r.app != null) {
9662 if (r.app.executingServices.size() == 0) {
9663 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
9664 msg.obj = r.app;
9665 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
9666 }
9667 r.app.executingServices.add(r);
9668 }
9669 r.executeNesting++;
9670 r.executingStart = now;
9671 }
9672
9673 private final void sendServiceArgsLocked(ServiceRecord r,
9674 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009675 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009676 if (N == 0) {
9677 return;
9678 }
9679
Dianne Hackborn39792d22010-08-19 18:01:52 -07009680 while (r.pendingStarts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009681 try {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009682 ServiceRecord.StartItem si = r.pendingStarts.remove(0);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009683 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
9684 + r + " " + r.intent + " args=" + si.intent);
Dianne Hackborn3a28f222011-03-01 12:25:54 -08009685 if (si.intent == null && N > 1) {
9686 // If somehow we got a dummy null intent in the middle,
9687 // then skip it. DO NOT skip a null intent when it is
9688 // the only one in the list -- this is to support the
9689 // onStartCommand(null) case.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009690 continue;
9691 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07009692 si.deliveredTime = SystemClock.uptimeMillis();
9693 r.deliveredStarts.add(si);
9694 si.deliveryCount++;
Dianne Hackborn3a28f222011-03-01 12:25:54 -08009695 if (si.targetPermissionUid >= 0 && si.intent != null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07009696 grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
Dianne Hackborn7e269642010-08-25 19:50:20 -07009697 r.packageName, si.intent, si.getUriPermissionsLocked());
Dianne Hackborn39792d22010-08-19 18:01:52 -07009698 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07009699 bumpServiceExecutingLocked(r, "start");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009700 if (!oomAdjusted) {
9701 oomAdjusted = true;
9702 updateOomAdjLocked(r.app);
9703 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009704 int flags = 0;
9705 if (si.deliveryCount > 0) {
9706 flags |= Service.START_FLAG_RETRY;
9707 }
9708 if (si.doneExecutingCount > 0) {
9709 flags |= Service.START_FLAG_REDELIVERY;
9710 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07009711 r.app.thread.scheduleServiceArgs(r, si.taskRemoved, si.id, flags, si.intent);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009712 } catch (RemoteException e) {
9713 // Remote process gone... we'll let the normal cleanup take
9714 // care of this.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009715 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009716 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009717 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009718 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009719 break;
9720 }
9721 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009722 }
9723
9724 private final boolean requestServiceBindingLocked(ServiceRecord r,
9725 IntentBindRecord i, boolean rebind) {
9726 if (r.app == null || r.app.thread == null) {
9727 // If service is not currently running, can't yet bind.
9728 return false;
9729 }
9730 if ((!i.requested || rebind) && i.apps.size() > 0) {
9731 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009732 bumpServiceExecutingLocked(r, "bind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009733 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
9734 if (!rebind) {
9735 i.requested = true;
9736 }
9737 i.hasBound = true;
9738 i.doRebind = false;
9739 } catch (RemoteException e) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009740 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009741 return false;
9742 }
9743 }
9744 return true;
9745 }
9746
9747 private final void requestServiceBindingsLocked(ServiceRecord r) {
9748 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
9749 while (bindings.hasNext()) {
9750 IntentBindRecord i = bindings.next();
9751 if (!requestServiceBindingLocked(r, i, false)) {
9752 break;
9753 }
9754 }
9755 }
9756
9757 private final void realStartServiceLocked(ServiceRecord r,
9758 ProcessRecord app) throws RemoteException {
9759 if (app.thread == null) {
9760 throw new RemoteException();
9761 }
9762
9763 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -07009764 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009765
9766 app.services.add(r);
Dianne Hackborn287952c2010-09-22 22:34:31 -07009767 bumpServiceExecutingLocked(r, "create");
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009768 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009769
9770 boolean created = false;
9771 try {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07009772 mStringBuilder.setLength(0);
9773 r.intent.getIntent().toShortString(mStringBuilder, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009774 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009775 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -07009776 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009777 synchronized (r.stats.getBatteryStats()) {
9778 r.stats.startLaunchedLocked();
9779 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07009780 ensurePackageDexOpt(r.serviceInfo.packageName);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04009781 app.thread.scheduleCreateService(r, r.serviceInfo,
9782 compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo));
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009783 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009784 created = true;
9785 } finally {
9786 if (!created) {
9787 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009788 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009789 }
9790 }
9791
9792 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009793
9794 // If the service is in the started state, and there are no
9795 // pending arguments, then fake up one so its onStartCommand() will
9796 // be called.
9797 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07009798 r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
9799 null, -1));
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009800 }
9801
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009802 sendServiceArgsLocked(r, true);
9803 }
9804
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009805 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
9806 boolean allowCancel) {
9807 boolean canceled = false;
9808
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009809 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009810 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -07009811 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009812
Dianne Hackborn070783f2010-12-29 16:46:28 -08009813 if ((r.serviceInfo.applicationInfo.flags
9814 &ApplicationInfo.FLAG_PERSISTENT) != 0) {
9815 minDuration /= 4;
9816 }
9817
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009818 // Any delivered but not yet finished starts should be put back
9819 // on the pending list.
9820 final int N = r.deliveredStarts.size();
9821 if (N > 0) {
9822 for (int i=N-1; i>=0; i--) {
9823 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
Dianne Hackborn39792d22010-08-19 18:01:52 -07009824 si.removeUriPermissionsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009825 if (si.intent == null) {
9826 // We'll generate this again if needed.
9827 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
9828 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
9829 r.pendingStarts.add(0, si);
9830 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
9831 dur *= 2;
9832 if (minDuration < dur) minDuration = dur;
9833 if (resetTime < dur) resetTime = dur;
9834 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009835 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009836 + r.name);
9837 canceled = true;
9838 }
9839 }
9840 r.deliveredStarts.clear();
9841 }
9842
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009843 r.totalRestartCount++;
9844 if (r.restartDelay == 0) {
9845 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009846 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009847 } else {
9848 // If it has been a "reasonably long time" since the service
9849 // was started, then reset our restart duration back to
9850 // the beginning, so we don't infinitely increase the duration
9851 // on a service that just occasionally gets killed (which is
9852 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009853 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009854 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009855 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009856 } else {
Dianne Hackborn070783f2010-12-29 16:46:28 -08009857 if ((r.serviceInfo.applicationInfo.flags
9858 &ApplicationInfo.FLAG_PERSISTENT) != 0) {
9859 // Services in peristent processes will restart much more
9860 // quickly, since they are pretty important. (Think SystemUI).
9861 r.restartDelay += minDuration/2;
9862 } else {
9863 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
9864 if (r.restartDelay < minDuration) {
9865 r.restartDelay = minDuration;
9866 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009867 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009868 }
9869 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009870
9871 r.nextRestartTime = now + r.restartDelay;
9872
9873 // Make sure that we don't end up restarting a bunch of services
9874 // all at the same time.
9875 boolean repeat;
9876 do {
9877 repeat = false;
9878 for (int i=mRestartingServices.size()-1; i>=0; i--) {
9879 ServiceRecord r2 = mRestartingServices.get(i);
9880 if (r2 != r && r.nextRestartTime
9881 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
9882 && r.nextRestartTime
9883 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
9884 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
9885 r.restartDelay = r.nextRestartTime - now;
9886 repeat = true;
9887 break;
9888 }
9889 }
9890 } while (repeat);
9891
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009892 if (!mRestartingServices.contains(r)) {
9893 mRestartingServices.add(r);
9894 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009895
Dianne Hackbornd8a43f62009-08-17 23:33:56 -07009896 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009897
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009898 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07009899 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009900 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009901 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009902 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -08009903 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009904 r.shortName, r.restartDelay);
9905
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009906 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009907 }
9908
9909 final void performServiceRestartLocked(ServiceRecord r) {
9910 if (!mRestartingServices.contains(r)) {
9911 return;
9912 }
9913 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
9914 }
9915
9916 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
9917 if (r.restartDelay == 0) {
9918 return false;
9919 }
9920 r.resetRestartCounter();
9921 mRestartingServices.remove(r);
9922 mHandler.removeCallbacks(r.restarter);
9923 return true;
9924 }
9925
9926 private final boolean bringUpServiceLocked(ServiceRecord r,
9927 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009928 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009929 //r.dump(" ");
9930
Dianne Hackborn36124872009-10-08 16:22:03 -07009931 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009932 sendServiceArgsLocked(r, false);
9933 return true;
9934 }
9935
9936 if (!whileRestarting && r.restartDelay > 0) {
9937 // If waiting for a restart, then do nothing.
9938 return true;
9939 }
9940
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009941 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009942
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009943 // We are now bringing the service up, so no longer in the
9944 // restarting state.
9945 mRestartingServices.remove(r);
9946
Dianne Hackborne7f97212011-02-24 14:40:20 -08009947 // Service is now being launched, its package can't be stopped.
9948 try {
9949 AppGlobals.getPackageManager().setPackageStoppedState(
9950 r.packageName, false);
9951 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08009952 } catch (IllegalArgumentException e) {
9953 Slog.w(TAG, "Failed trying to unstop package "
9954 + r.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08009955 }
9956
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009957 final String appName = r.processName;
9958 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
9959 if (app != null && app.thread != null) {
9960 try {
Dianne Hackborn6c418d52011-06-29 14:05:33 -07009961 app.addPackage(r.appInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009962 realStartServiceLocked(r, app);
9963 return true;
9964 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009965 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009966 }
9967
9968 // If a dead object exception was thrown -- fall through to
9969 // restart the application.
9970 }
9971
Dianne Hackborn36124872009-10-08 16:22:03 -07009972 // Not running -- get it started, and enqueue this service record
9973 // to be executed when the app comes up.
9974 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
9975 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009976 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -07009977 + r.appInfo.packageName + "/"
9978 + r.appInfo.uid + " for service "
9979 + r.intent.getIntent() + ": process is bad");
9980 bringDownServiceLocked(r, true);
9981 return false;
9982 }
9983
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009984 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009985 mPendingServices.add(r);
9986 }
Dianne Hackborn36124872009-10-08 16:22:03 -07009987
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009988 return true;
9989 }
9990
9991 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009992 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009993 //r.dump(" ");
9994
9995 // Does it still need to run?
9996 if (!force && r.startRequested) {
9997 return;
9998 }
9999 if (r.connections.size() > 0) {
10000 if (!force) {
10001 // XXX should probably keep a count of the number of auto-create
10002 // connections directly in the service.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010003 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010004 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010005 ArrayList<ConnectionRecord> cr = it.next();
10006 for (int i=0; i<cr.size(); i++) {
10007 if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
10008 return;
10009 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010010 }
10011 }
10012 }
10013
10014 // Report to all of the connections that the service is no longer
10015 // available.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010016 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010017 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010018 ArrayList<ConnectionRecord> c = it.next();
10019 for (int i=0; i<c.size(); i++) {
Dianne Hackborn130b0d22011-07-26 22:07:48 -070010020 ConnectionRecord cr = c.get(i);
10021 // There is still a connection to the service that is
10022 // being brought down. Mark it as dead.
10023 cr.serviceDead = true;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010024 try {
Dianne Hackborn130b0d22011-07-26 22:07:48 -070010025 cr.conn.connected(r.name, null);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010026 } catch (Exception e) {
10027 Slog.w(TAG, "Failure disconnecting service " + r.name +
10028 " to connection " + c.get(i).conn.asBinder() +
10029 " (in " + c.get(i).binding.client.processName + ")", e);
10030 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010031 }
10032 }
10033 }
10034
10035 // Tell the service that it has been unbound.
10036 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
10037 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
10038 while (it.hasNext()) {
10039 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010040 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010041 + ": hasBound=" + ibr.hasBound);
10042 if (r.app != null && r.app.thread != null && ibr.hasBound) {
10043 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010044 bumpServiceExecutingLocked(r, "bring down unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010045 updateOomAdjLocked(r.app);
10046 ibr.hasBound = false;
10047 r.app.thread.scheduleUnbindService(r,
10048 ibr.intent.getIntent());
10049 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010050 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010051 + r.shortName, e);
10052 serviceDoneExecutingLocked(r, true);
10053 }
10054 }
10055 }
10056 }
10057
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010058 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010059 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010060 System.identityHashCode(r), r.shortName,
10061 (r.app != null) ? r.app.pid : -1);
10062
10063 mServices.remove(r.name);
10064 mServicesByIntent.remove(r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010065 r.totalRestartCount = 0;
10066 unscheduleServiceRestartLocked(r);
10067
10068 // Also make sure it is not on the pending list.
10069 int N = mPendingServices.size();
10070 for (int i=0; i<N; i++) {
10071 if (mPendingServices.get(i) == r) {
10072 mPendingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010073 if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010074 i--;
10075 N--;
10076 }
10077 }
10078
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010079 r.cancelNotification();
10080 r.isForeground = false;
10081 r.foregroundId = 0;
10082 r.foregroundNoti = null;
10083
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010084 // Clear start entries.
Dianne Hackborn39792d22010-08-19 18:01:52 -070010085 r.clearDeliveredStartsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010086 r.pendingStarts.clear();
10087
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010088 if (r.app != null) {
10089 synchronized (r.stats.getBatteryStats()) {
10090 r.stats.stopLaunchedLocked();
10091 }
10092 r.app.services.remove(r);
10093 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010094 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010095 bumpServiceExecutingLocked(r, "stop");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010096 mStoppingServices.add(r);
10097 updateOomAdjLocked(r.app);
10098 r.app.thread.scheduleStopService(r);
10099 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010100 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010101 + r.shortName, e);
10102 serviceDoneExecutingLocked(r, true);
10103 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010104 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010105 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010106 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010107 TAG, "Removed service that has no process: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010108 }
10109 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010110 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010111 TAG, "Removed service that is not running: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010112 }
Vairavan Srinivasana207ce22010-12-23 13:51:48 -080010113
10114 if (r.bindings.size() > 0) {
10115 r.bindings.clear();
10116 }
10117
10118 if (r.restarter instanceof ServiceRestarter) {
10119 ((ServiceRestarter)r.restarter).setService(null);
10120 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010121 }
10122
10123 ComponentName startServiceLocked(IApplicationThread caller,
10124 Intent service, String resolvedType,
10125 int callingPid, int callingUid) {
10126 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010127 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010128 + " type=" + resolvedType + " args=" + service.getExtras());
10129
10130 if (caller != null) {
10131 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10132 if (callerApp == null) {
10133 throw new SecurityException(
10134 "Unable to find app for caller " + caller
10135 + " (pid=" + Binder.getCallingPid()
10136 + ") when starting service " + service);
10137 }
10138 }
10139
10140 ServiceLookupResult res =
10141 retrieveServiceLocked(service, resolvedType,
10142 callingPid, callingUid);
10143 if (res == null) {
10144 return null;
10145 }
10146 if (res.record == null) {
10147 return new ComponentName("!", res.permission != null
10148 ? res.permission : "private to package");
10149 }
10150 ServiceRecord r = res.record;
Dianne Hackborn39792d22010-08-19 18:01:52 -070010151 int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
10152 callingUid, r.packageName, service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010153 if (unscheduleServiceRestartLocked(r)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010154 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010155 }
10156 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010157 r.callStart = false;
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010158 r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
Dianne Hackborn39792d22010-08-19 18:01:52 -070010159 service, targetPermissionUid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010160 r.lastActivity = SystemClock.uptimeMillis();
10161 synchronized (r.stats.getBatteryStats()) {
10162 r.stats.startRunningLocked();
10163 }
10164 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
10165 return new ComponentName("!", "Service process is bad");
10166 }
10167 return r.name;
10168 }
10169 }
10170
10171 public ComponentName startService(IApplicationThread caller, Intent service,
10172 String resolvedType) {
10173 // Refuse possible leaked file descriptors
10174 if (service != null && service.hasFileDescriptors() == true) {
10175 throw new IllegalArgumentException("File descriptors passed in Intent");
10176 }
10177
10178 synchronized(this) {
10179 final int callingPid = Binder.getCallingPid();
10180 final int callingUid = Binder.getCallingUid();
10181 final long origId = Binder.clearCallingIdentity();
10182 ComponentName res = startServiceLocked(caller, service,
10183 resolvedType, callingPid, callingUid);
10184 Binder.restoreCallingIdentity(origId);
10185 return res;
10186 }
10187 }
10188
10189 ComponentName startServiceInPackage(int uid,
10190 Intent service, String resolvedType) {
10191 synchronized(this) {
10192 final long origId = Binder.clearCallingIdentity();
10193 ComponentName res = startServiceLocked(null, service,
10194 resolvedType, -1, uid);
10195 Binder.restoreCallingIdentity(origId);
10196 return res;
10197 }
10198 }
10199
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010200 private void stopServiceLocked(ServiceRecord service) {
10201 synchronized (service.stats.getBatteryStats()) {
10202 service.stats.stopRunningLocked();
10203 }
10204 service.startRequested = false;
10205 service.callStart = false;
10206 bringDownServiceLocked(service, false);
10207 }
10208
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010209 public int stopService(IApplicationThread caller, Intent service,
10210 String resolvedType) {
10211 // Refuse possible leaked file descriptors
10212 if (service != null && service.hasFileDescriptors() == true) {
10213 throw new IllegalArgumentException("File descriptors passed in Intent");
10214 }
10215
10216 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010217 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010218 + " type=" + resolvedType);
10219
10220 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10221 if (caller != null && callerApp == null) {
10222 throw new SecurityException(
10223 "Unable to find app for caller " + caller
10224 + " (pid=" + Binder.getCallingPid()
10225 + ") when stopping service " + service);
10226 }
10227
10228 // If this service is active, make sure it is stopped.
10229 ServiceLookupResult r = findServiceLocked(service, resolvedType);
10230 if (r != null) {
10231 if (r.record != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010232 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010233 try {
10234 stopServiceLocked(r.record);
10235 } finally {
10236 Binder.restoreCallingIdentity(origId);
10237 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010238 return 1;
10239 }
10240 return -1;
10241 }
10242 }
10243
10244 return 0;
10245 }
10246
10247 public IBinder peekService(Intent service, String resolvedType) {
10248 // Refuse possible leaked file descriptors
10249 if (service != null && service.hasFileDescriptors() == true) {
10250 throw new IllegalArgumentException("File descriptors passed in Intent");
10251 }
10252
10253 IBinder ret = null;
10254
10255 synchronized(this) {
10256 ServiceLookupResult r = findServiceLocked(service, resolvedType);
10257
10258 if (r != null) {
10259 // r.record is null if findServiceLocked() failed the caller permission check
10260 if (r.record == null) {
10261 throw new SecurityException(
10262 "Permission Denial: Accessing service " + r.record.name
10263 + " from pid=" + Binder.getCallingPid()
10264 + ", uid=" + Binder.getCallingUid()
10265 + " requires " + r.permission);
10266 }
10267 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
10268 if (ib != null) {
10269 ret = ib.binder;
10270 }
10271 }
10272 }
10273
10274 return ret;
10275 }
10276
10277 public boolean stopServiceToken(ComponentName className, IBinder token,
10278 int startId) {
10279 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010280 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010281 + " " + token + " startId=" + startId);
10282 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010283 if (r != null) {
10284 if (startId >= 0) {
10285 // Asked to only stop if done with all work. Note that
10286 // to avoid leaks, we will take this as dropping all
10287 // start items up to and including this one.
10288 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
10289 if (si != null) {
10290 while (r.deliveredStarts.size() > 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -070010291 ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
10292 cur.removeUriPermissionsLocked();
10293 if (cur == si) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010294 break;
10295 }
10296 }
10297 }
10298
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010299 if (r.getLastStartId() != startId) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010300 return false;
10301 }
10302
10303 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010304 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010305 + " is last, but have " + r.deliveredStarts.size()
10306 + " remaining args");
10307 }
10308 }
10309
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010310 synchronized (r.stats.getBatteryStats()) {
10311 r.stats.stopRunningLocked();
10312 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010313 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010314 }
10315 final long origId = Binder.clearCallingIdentity();
10316 bringDownServiceLocked(r, false);
10317 Binder.restoreCallingIdentity(origId);
10318 return true;
10319 }
10320 }
10321 return false;
10322 }
10323
10324 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010325 int id, Notification notification, boolean removeNotification) {
10326 final long origId = Binder.clearCallingIdentity();
10327 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010328 synchronized(this) {
10329 ServiceRecord r = findServiceLocked(className, token);
10330 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010331 if (id != 0) {
10332 if (notification == null) {
10333 throw new IllegalArgumentException("null notification");
10334 }
10335 if (r.foregroundId != id) {
10336 r.cancelNotification();
10337 r.foregroundId = id;
10338 }
10339 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
10340 r.foregroundNoti = notification;
10341 r.isForeground = true;
10342 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010343 if (r.app != null) {
10344 updateServiceForegroundLocked(r.app, true);
10345 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010346 } else {
10347 if (r.isForeground) {
10348 r.isForeground = false;
10349 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -070010350 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010351 updateServiceForegroundLocked(r.app, true);
10352 }
10353 }
10354 if (removeNotification) {
10355 r.cancelNotification();
10356 r.foregroundId = 0;
10357 r.foregroundNoti = null;
10358 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010359 }
10360 }
10361 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010362 } finally {
10363 Binder.restoreCallingIdentity(origId);
10364 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010365 }
10366
10367 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
10368 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -070010369 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010370 if (sr.isForeground) {
10371 anyForeground = true;
10372 break;
10373 }
10374 }
10375 if (anyForeground != proc.foregroundServices) {
10376 proc.foregroundServices = anyForeground;
10377 if (oomAdj) {
10378 updateOomAdjLocked();
10379 }
10380 }
10381 }
10382
10383 public int bindService(IApplicationThread caller, IBinder token,
10384 Intent service, String resolvedType,
10385 IServiceConnection connection, int flags) {
10386 // Refuse possible leaked file descriptors
10387 if (service != null && service.hasFileDescriptors() == true) {
10388 throw new IllegalArgumentException("File descriptors passed in Intent");
10389 }
10390
10391 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010392 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010393 + " type=" + resolvedType + " conn=" + connection.asBinder()
10394 + " flags=0x" + Integer.toHexString(flags));
10395 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10396 if (callerApp == null) {
10397 throw new SecurityException(
10398 "Unable to find app for caller " + caller
10399 + " (pid=" + Binder.getCallingPid()
10400 + ") when binding service " + service);
10401 }
10402
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010403 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010404 if (token != null) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -070010405 activity = mMainStack.isInStackLocked(token);
10406 if (activity == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010407 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010408 return 0;
10409 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010410 }
10411
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010412 int clientLabel = 0;
10413 PendingIntent clientIntent = null;
10414
10415 if (callerApp.info.uid == Process.SYSTEM_UID) {
10416 // Hacky kind of thing -- allow system stuff to tell us
10417 // what they are, so we can report this elsewhere for
10418 // others to know why certain services are running.
10419 try {
10420 clientIntent = (PendingIntent)service.getParcelableExtra(
10421 Intent.EXTRA_CLIENT_INTENT);
10422 } catch (RuntimeException e) {
10423 }
10424 if (clientIntent != null) {
10425 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
10426 if (clientLabel != 0) {
10427 // There are no useful extras in the intent, trash them.
10428 // System code calling with this stuff just needs to know
10429 // this will happen.
10430 service = service.cloneFilter();
10431 }
10432 }
10433 }
10434
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010435 ServiceLookupResult res =
10436 retrieveServiceLocked(service, resolvedType,
10437 Binder.getCallingPid(), Binder.getCallingUid());
10438 if (res == null) {
10439 return 0;
10440 }
10441 if (res.record == null) {
10442 return -1;
10443 }
10444 ServiceRecord s = res.record;
10445
10446 final long origId = Binder.clearCallingIdentity();
10447
10448 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010449 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010450 + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010451 }
10452
10453 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
10454 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010455 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010456
10457 IBinder binder = connection.asBinder();
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010458 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
10459 if (clist == null) {
10460 clist = new ArrayList<ConnectionRecord>();
10461 s.connections.put(binder, clist);
10462 }
10463 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010464 b.connections.add(c);
10465 if (activity != null) {
10466 if (activity.connections == null) {
10467 activity.connections = new HashSet<ConnectionRecord>();
10468 }
10469 activity.connections.add(c);
10470 }
10471 b.client.connections.add(c);
Dianne Hackbornc68c9132011-07-29 01:25:18 -070010472 if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) {
10473 b.client.hasAboveClient = true;
10474 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010475 clist = mServiceConnections.get(binder);
10476 if (clist == null) {
10477 clist = new ArrayList<ConnectionRecord>();
10478 mServiceConnections.put(binder, clist);
10479 }
10480 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010481
10482 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
10483 s.lastActivity = SystemClock.uptimeMillis();
10484 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
10485 return 0;
10486 }
10487 }
10488
10489 if (s.app != null) {
10490 // This could have made the service more important.
10491 updateOomAdjLocked(s.app);
10492 }
10493
Joe Onorato8a9b2202010-02-26 18:56:32 -080010494 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010495 + ": received=" + b.intent.received
10496 + " apps=" + b.intent.apps.size()
10497 + " doRebind=" + b.intent.doRebind);
10498
10499 if (s.app != null && b.intent.received) {
10500 // Service is already running, so we can immediately
10501 // publish the connection.
10502 try {
10503 c.conn.connected(s.name, b.intent.binder);
10504 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010505 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010506 + " to connection " + c.conn.asBinder()
10507 + " (in " + c.binding.client.processName + ")", e);
10508 }
10509
10510 // If this is the first app connected back to this binding,
10511 // and the service had previously asked to be told when
10512 // rebound, then do so.
10513 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
10514 requestServiceBindingLocked(s, b.intent, true);
10515 }
10516 } else if (!b.intent.requested) {
10517 requestServiceBindingLocked(s, b.intent, false);
10518 }
10519
10520 Binder.restoreCallingIdentity(origId);
10521 }
10522
10523 return 1;
10524 }
10525
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010526 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010527 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010528 IBinder binder = c.conn.asBinder();
10529 AppBindRecord b = c.binding;
10530 ServiceRecord s = b.service;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010531 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
10532 if (clist != null) {
10533 clist.remove(c);
10534 if (clist.size() == 0) {
10535 s.connections.remove(binder);
10536 }
10537 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010538 b.connections.remove(c);
10539 if (c.activity != null && c.activity != skipAct) {
10540 if (c.activity.connections != null) {
10541 c.activity.connections.remove(c);
10542 }
10543 }
10544 if (b.client != skipApp) {
10545 b.client.connections.remove(c);
Dianne Hackbornc68c9132011-07-29 01:25:18 -070010546 if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) {
10547 b.client.updateHasAboveClientLocked();
10548 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010549 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010550 clist = mServiceConnections.get(binder);
10551 if (clist != null) {
10552 clist.remove(c);
10553 if (clist.size() == 0) {
10554 mServiceConnections.remove(binder);
10555 }
10556 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010557
10558 if (b.connections.size() == 0) {
10559 b.intent.apps.remove(b.client);
10560 }
10561
Dianne Hackborn130b0d22011-07-26 22:07:48 -070010562 if (!c.serviceDead) {
10563 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
10564 + ": shouldUnbind=" + b.intent.hasBound);
10565 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
10566 && b.intent.hasBound) {
10567 try {
10568 bumpServiceExecutingLocked(s, "unbind");
10569 updateOomAdjLocked(s.app);
10570 b.intent.hasBound = false;
10571 // Assume the client doesn't want to know about a rebind;
10572 // we will deal with that later if it asks for one.
10573 b.intent.doRebind = false;
10574 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
10575 } catch (Exception e) {
10576 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
10577 serviceDoneExecutingLocked(s, true);
10578 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010579 }
Dianne Hackborn130b0d22011-07-26 22:07:48 -070010580
10581 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
10582 bringDownServiceLocked(s, false);
10583 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010584 }
10585 }
10586
10587 public boolean unbindService(IServiceConnection connection) {
10588 synchronized (this) {
10589 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010590 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010591 ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
10592 if (clist == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010593 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010594 + connection.asBinder());
10595 return false;
10596 }
10597
10598 final long origId = Binder.clearCallingIdentity();
10599
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010600 while (clist.size() > 0) {
10601 ConnectionRecord r = clist.get(0);
10602 removeConnectionLocked(r, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010603
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010604 if (r.binding.service.app != null) {
10605 // This could have made the service less important.
10606 updateOomAdjLocked(r.binding.service.app);
10607 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010608 }
10609
10610 Binder.restoreCallingIdentity(origId);
10611 }
10612
10613 return true;
10614 }
10615
10616 public void publishService(IBinder token, Intent intent, IBinder service) {
10617 // Refuse possible leaked file descriptors
10618 if (intent != null && intent.hasFileDescriptors() == true) {
10619 throw new IllegalArgumentException("File descriptors passed in Intent");
10620 }
10621
10622 synchronized(this) {
10623 if (!(token instanceof ServiceRecord)) {
10624 throw new IllegalArgumentException("Invalid service token");
10625 }
10626 ServiceRecord r = (ServiceRecord)token;
10627
10628 final long origId = Binder.clearCallingIdentity();
10629
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010630 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010631 + " " + intent + ": " + service);
10632 if (r != null) {
10633 Intent.FilterComparison filter
10634 = new Intent.FilterComparison(intent);
10635 IntentBindRecord b = r.bindings.get(filter);
10636 if (b != null && !b.received) {
10637 b.binder = service;
10638 b.requested = true;
10639 b.received = true;
10640 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010641 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010642 = r.connections.values().iterator();
10643 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010644 ArrayList<ConnectionRecord> clist = it.next();
10645 for (int i=0; i<clist.size(); i++) {
10646 ConnectionRecord c = clist.get(i);
10647 if (!filter.equals(c.binding.intent.intent)) {
10648 if (DEBUG_SERVICE) Slog.v(
10649 TAG, "Not publishing to: " + c);
10650 if (DEBUG_SERVICE) Slog.v(
10651 TAG, "Bound intent: " + c.binding.intent.intent);
10652 if (DEBUG_SERVICE) Slog.v(
10653 TAG, "Published intent: " + intent);
10654 continue;
10655 }
10656 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
10657 try {
10658 c.conn.connected(r.name, service);
10659 } catch (Exception e) {
10660 Slog.w(TAG, "Failure sending service " + r.name +
10661 " to connection " + c.conn.asBinder() +
10662 " (in " + c.binding.client.processName + ")", e);
10663 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010664 }
10665 }
10666 }
10667 }
10668
10669 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
10670
10671 Binder.restoreCallingIdentity(origId);
10672 }
10673 }
10674 }
10675
10676 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
10677 // Refuse possible leaked file descriptors
10678 if (intent != null && intent.hasFileDescriptors() == true) {
10679 throw new IllegalArgumentException("File descriptors passed in Intent");
10680 }
10681
10682 synchronized(this) {
10683 if (!(token instanceof ServiceRecord)) {
10684 throw new IllegalArgumentException("Invalid service token");
10685 }
10686 ServiceRecord r = (ServiceRecord)token;
10687
10688 final long origId = Binder.clearCallingIdentity();
10689
10690 if (r != null) {
10691 Intent.FilterComparison filter
10692 = new Intent.FilterComparison(intent);
10693 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010694 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010695 + " at " + b + ": apps="
10696 + (b != null ? b.apps.size() : 0));
10697 if (b != null) {
10698 if (b.apps.size() > 0) {
10699 // Applications have already bound since the last
10700 // unbind, so just rebind right here.
10701 requestServiceBindingLocked(r, b, true);
10702 } else {
10703 // Note to tell the service the next time there is
10704 // a new client.
10705 b.doRebind = true;
10706 }
10707 }
10708
10709 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
10710
10711 Binder.restoreCallingIdentity(origId);
10712 }
10713 }
10714 }
10715
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010716 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010717 synchronized(this) {
10718 if (!(token instanceof ServiceRecord)) {
10719 throw new IllegalArgumentException("Invalid service token");
10720 }
10721 ServiceRecord r = (ServiceRecord)token;
10722 boolean inStopping = mStoppingServices.contains(token);
10723 if (r != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010724 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010725 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010726 + " with incorrect token: given " + token
10727 + ", expected " + r);
10728 return;
10729 }
10730
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010731 if (type == 1) {
10732 // This is a call from a service start... take care of
10733 // book-keeping.
10734 r.callStart = true;
10735 switch (res) {
10736 case Service.START_STICKY_COMPATIBILITY:
10737 case Service.START_STICKY: {
10738 // We are done with the associated start arguments.
10739 r.findDeliveredStart(startId, true);
10740 // Don't stop if killed.
10741 r.stopIfKilled = false;
10742 break;
10743 }
10744 case Service.START_NOT_STICKY: {
10745 // We are done with the associated start arguments.
10746 r.findDeliveredStart(startId, true);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010747 if (r.getLastStartId() == startId) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010748 // There is no more work, and this service
10749 // doesn't want to hang around if killed.
10750 r.stopIfKilled = true;
10751 }
10752 break;
10753 }
10754 case Service.START_REDELIVER_INTENT: {
10755 // We'll keep this item until they explicitly
10756 // call stop for it, but keep track of the fact
10757 // that it was delivered.
10758 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
10759 if (si != null) {
10760 si.deliveryCount = 0;
10761 si.doneExecutingCount++;
10762 // Don't stop if killed.
10763 r.stopIfKilled = true;
10764 }
10765 break;
10766 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010767 case Service.START_TASK_REMOVED_COMPLETE: {
10768 // Special processing for onTaskRemoved(). Don't
10769 // impact normal onStartCommand() processing.
10770 r.findDeliveredStart(startId, true);
10771 break;
10772 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010773 default:
10774 throw new IllegalArgumentException(
10775 "Unknown service start result: " + res);
10776 }
10777 if (res == Service.START_STICKY_COMPATIBILITY) {
10778 r.callStart = false;
10779 }
10780 }
10781
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010782 final long origId = Binder.clearCallingIdentity();
10783 serviceDoneExecutingLocked(r, inStopping);
10784 Binder.restoreCallingIdentity(origId);
10785 } else {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010786 Slog.w(TAG, "Done executing unknown service from pid "
10787 + Binder.getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010788 }
10789 }
10790 }
10791
10792 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010793 if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
10794 + ": nesting=" + r.executeNesting
10795 + ", inStopping=" + inStopping + ", app=" + r.app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070010796 else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010797 r.executeNesting--;
10798 if (r.executeNesting <= 0 && r.app != null) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010799 if (DEBUG_SERVICE) Slog.v(TAG,
10800 "Nesting at 0 of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010801 r.app.executingServices.remove(r);
10802 if (r.app.executingServices.size() == 0) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010803 if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,
10804 "No more executingServices of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010805 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
10806 }
10807 if (inStopping) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010808 if (DEBUG_SERVICE) Slog.v(TAG,
10809 "doneExecuting remove stopping " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010810 mStoppingServices.remove(r);
Mattias Petersson3996b412010-10-27 09:32:51 +020010811 r.bindings.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010812 }
10813 updateOomAdjLocked(r.app);
10814 }
10815 }
10816
10817 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010818 String anrMessage = null;
10819
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010820 synchronized(this) {
10821 if (proc.executingServices.size() == 0 || proc.thread == null) {
10822 return;
10823 }
10824 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
10825 Iterator<ServiceRecord> it = proc.executingServices.iterator();
10826 ServiceRecord timeout = null;
10827 long nextTime = 0;
10828 while (it.hasNext()) {
10829 ServiceRecord sr = it.next();
10830 if (sr.executingStart < maxTime) {
10831 timeout = sr;
10832 break;
10833 }
10834 if (sr.executingStart > nextTime) {
10835 nextTime = sr.executingStart;
10836 }
10837 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010838 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010839 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010840 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010841 } else {
10842 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
10843 msg.obj = proc;
10844 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
10845 }
10846 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070010847
10848 if (anrMessage != null) {
10849 appNotResponding(proc, null, null, anrMessage);
10850 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010851 }
10852
10853 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070010854 // BACKUP AND RESTORE
10855 // =========================================================
10856
10857 // Cause the target app to be launched if necessary and its backup agent
10858 // instantiated. The backup agent will invoke backupAgentCreated() on the
10859 // activity manager to announce its creation.
10860 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010861 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070010862 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
10863
10864 synchronized(this) {
10865 // !!! TODO: currently no check here that we're already bound
10866 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
10867 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
10868 synchronized (stats) {
10869 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
10870 }
10871
Dianne Hackborne7f97212011-02-24 14:40:20 -080010872 // Backup agent is now in use, its package can't be stopped.
10873 try {
10874 AppGlobals.getPackageManager().setPackageStoppedState(
10875 app.packageName, false);
10876 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -080010877 } catch (IllegalArgumentException e) {
10878 Slog.w(TAG, "Failed trying to unstop package "
10879 + app.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -080010880 }
10881
Christopher Tate181fafa2009-05-14 11:12:14 -070010882 BackupRecord r = new BackupRecord(ss, app, backupMode);
Christopher Tate4a627c72011-04-01 14:43:32 -070010883 ComponentName hostingName = (backupMode == IApplicationThread.BACKUP_MODE_INCREMENTAL)
10884 ? new ComponentName(app.packageName, app.backupAgentName)
10885 : new ComponentName("android", "FullBackupAgent");
Christopher Tate181fafa2009-05-14 11:12:14 -070010886 // startProcessLocked() returns existing proc's record if it's already running
10887 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070010888 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070010889 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010890 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070010891 return false;
10892 }
10893
10894 r.app = proc;
10895 mBackupTarget = r;
10896 mBackupAppName = app.packageName;
10897
Christopher Tate6fa95972009-06-05 18:43:55 -070010898 // Try not to kill the process during backup
10899 updateOomAdjLocked(proc);
10900
Christopher Tate181fafa2009-05-14 11:12:14 -070010901 // If the process is already attached, schedule the creation of the backup agent now.
10902 // If it is not yet live, this will be done when it attaches to the framework.
10903 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010904 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070010905 try {
Dianne Hackborne2515ee2011-04-27 18:52:56 -040010906 proc.thread.scheduleCreateBackupAgent(app,
10907 compatibilityInfoForPackageLocked(app), backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070010908 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070010909 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070010910 }
10911 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010912 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070010913 }
10914 // Invariants: at this point, the target app process exists and the application
10915 // is either already running or in the process of coming up. mBackupTarget and
10916 // mBackupAppName describe the app, so that when it binds back to the AM we
10917 // know that it's scheduled for a backup-agent operation.
10918 }
10919
10920 return true;
10921 }
10922
10923 // A backup agent has just come up
10924 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010925 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070010926 + " = " + agent);
10927
10928 synchronized(this) {
10929 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010930 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070010931 return;
10932 }
Dianne Hackborn06740692010-09-22 22:46:21 -070010933 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010934
Dianne Hackborn06740692010-09-22 22:46:21 -070010935 long oldIdent = Binder.clearCallingIdentity();
10936 try {
10937 IBackupManager bm = IBackupManager.Stub.asInterface(
10938 ServiceManager.getService(Context.BACKUP_SERVICE));
10939 bm.agentConnected(agentPackageName, agent);
10940 } catch (RemoteException e) {
10941 // can't happen; the backup manager service is local
10942 } catch (Exception e) {
10943 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
10944 e.printStackTrace();
10945 } finally {
10946 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070010947 }
10948 }
10949
10950 // done with this agent
10951 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010952 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070010953 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010954 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070010955 return;
10956 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010957
10958 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070010959 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010960 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070010961 return;
10962 }
10963
Christopher Tate181fafa2009-05-14 11:12:14 -070010964 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010965 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070010966 return;
10967 }
10968
Christopher Tate6fa95972009-06-05 18:43:55 -070010969 ProcessRecord proc = mBackupTarget.app;
10970 mBackupTarget = null;
10971 mBackupAppName = null;
10972
10973 // Not backing this app up any more; reset its OOM adjustment
10974 updateOomAdjLocked(proc);
10975
Christopher Tatec7b31e32009-06-10 15:49:30 -070010976 // If the app crashed during backup, 'thread' will be null here
10977 if (proc.thread != null) {
10978 try {
Dianne Hackborne2515ee2011-04-27 18:52:56 -040010979 proc.thread.scheduleDestroyBackupAgent(appInfo,
10980 compatibilityInfoForPackageLocked(appInfo));
Christopher Tatec7b31e32009-06-10 15:49:30 -070010981 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010982 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070010983 e.printStackTrace();
10984 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010985 }
Christopher Tate181fafa2009-05-14 11:12:14 -070010986 }
10987 }
10988 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010989 // BROADCASTS
10990 // =========================================================
10991
Josh Bartel7f208742010-02-25 11:01:44 -060010992 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010993 List cur) {
10994 final ContentResolver resolver = mContext.getContentResolver();
10995 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
10996 if (list == null) {
10997 return cur;
10998 }
10999 int N = list.size();
11000 for (int i=0; i<N; i++) {
11001 Intent intent = list.get(i);
11002 if (filter.match(resolver, intent, true, TAG) >= 0) {
11003 if (cur == null) {
11004 cur = new ArrayList<Intent>();
11005 }
11006 cur.add(intent);
11007 }
11008 }
11009 return cur;
11010 }
11011
11012 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011013 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011014 + mBroadcastsScheduled);
11015
11016 if (mBroadcastsScheduled) {
11017 return;
11018 }
11019 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
11020 mBroadcastsScheduled = true;
11021 }
11022
Dianne Hackborn6c418d52011-06-29 14:05:33 -070011023 public Intent registerReceiver(IApplicationThread caller, String callerPackage,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011024 IIntentReceiver receiver, IntentFilter filter, String permission) {
11025 synchronized(this) {
11026 ProcessRecord callerApp = null;
11027 if (caller != null) {
11028 callerApp = getRecordForAppLocked(caller);
11029 if (callerApp == null) {
11030 throw new SecurityException(
11031 "Unable to find app for caller " + caller
11032 + " (pid=" + Binder.getCallingPid()
11033 + ") when registering receiver " + receiver);
11034 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -070011035 if (callerApp.info.uid != Process.SYSTEM_UID &&
11036 !callerApp.pkgList.contains(callerPackage)) {
11037 throw new SecurityException("Given caller package " + callerPackage
11038 + " is not running in process " + callerApp);
11039 }
11040 } else {
11041 callerPackage = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011042 }
11043
11044 List allSticky = null;
11045
11046 // Look for any matching sticky broadcasts...
11047 Iterator actions = filter.actionsIterator();
11048 if (actions != null) {
11049 while (actions.hasNext()) {
11050 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -060011051 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011052 }
11053 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060011054 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011055 }
11056
11057 // The first sticky in the list is returned directly back to
11058 // the client.
11059 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
11060
Joe Onorato8a9b2202010-02-26 18:56:32 -080011061 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011062 + ": " + sticky);
11063
11064 if (receiver == null) {
11065 return sticky;
11066 }
11067
11068 ReceiverList rl
11069 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
11070 if (rl == null) {
11071 rl = new ReceiverList(this, callerApp,
11072 Binder.getCallingPid(),
11073 Binder.getCallingUid(), receiver);
11074 if (rl.app != null) {
11075 rl.app.receivers.add(rl);
11076 } else {
11077 try {
11078 receiver.asBinder().linkToDeath(rl, 0);
11079 } catch (RemoteException e) {
11080 return sticky;
11081 }
11082 rl.linkedToDeath = true;
11083 }
11084 mRegisteredReceivers.put(receiver.asBinder(), rl);
11085 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -070011086 BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage, permission);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011087 rl.add(bf);
11088 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011089 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011090 }
11091 mReceiverResolver.addFilter(bf);
11092
11093 // Enqueue broadcasts for all existing stickies that match
11094 // this filter.
11095 if (allSticky != null) {
11096 ArrayList receivers = new ArrayList();
11097 receivers.add(bf);
11098
11099 int N = allSticky.size();
11100 for (int i=0; i<N; i++) {
11101 Intent intent = (Intent)allSticky.get(i);
11102 BroadcastRecord r = new BroadcastRecord(intent, null,
11103 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011104 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011105 if (mParallelBroadcasts.size() == 0) {
11106 scheduleBroadcastsLocked();
11107 }
11108 mParallelBroadcasts.add(r);
11109 }
11110 }
11111
11112 return sticky;
11113 }
11114 }
11115
11116 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011117 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011118
11119 boolean doNext = false;
11120
11121 synchronized(this) {
11122 ReceiverList rl
11123 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
11124 if (rl != null) {
11125 if (rl.curBroadcast != null) {
11126 BroadcastRecord r = rl.curBroadcast;
11127 doNext = finishReceiverLocked(
11128 receiver.asBinder(), r.resultCode, r.resultData,
11129 r.resultExtras, r.resultAbort, true);
11130 }
11131
11132 if (rl.app != null) {
11133 rl.app.receivers.remove(rl);
11134 }
11135 removeReceiverLocked(rl);
11136 if (rl.linkedToDeath) {
11137 rl.linkedToDeath = false;
11138 rl.receiver.asBinder().unlinkToDeath(rl, 0);
11139 }
11140 }
11141 }
11142
11143 if (!doNext) {
11144 return;
11145 }
11146
11147 final long origId = Binder.clearCallingIdentity();
11148 processNextBroadcast(false);
11149 trimApplications();
11150 Binder.restoreCallingIdentity(origId);
11151 }
11152
11153 void removeReceiverLocked(ReceiverList rl) {
11154 mRegisteredReceivers.remove(rl.receiver.asBinder());
11155 int N = rl.size();
11156 for (int i=0; i<N; i++) {
11157 mReceiverResolver.removeFilter(rl.get(i));
11158 }
11159 }
11160
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070011161 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
11162 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
11163 ProcessRecord r = mLruProcesses.get(i);
11164 if (r.thread != null) {
11165 try {
11166 r.thread.dispatchPackageBroadcast(cmd, packages);
11167 } catch (RemoteException ex) {
11168 }
11169 }
11170 }
11171 }
11172
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011173 private final int broadcastIntentLocked(ProcessRecord callerApp,
11174 String callerPackage, Intent intent, String resolvedType,
11175 IIntentReceiver resultTo, int resultCode, String resultData,
11176 Bundle map, String requiredPermission,
11177 boolean ordered, boolean sticky, int callingPid, int callingUid) {
11178 intent = new Intent(intent);
11179
Dianne Hackborne7f97212011-02-24 14:40:20 -080011180 // By default broadcasts do not go to stopped apps.
11181 intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
11182
Joe Onorato8a9b2202010-02-26 18:56:32 -080011183 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011184 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
11185 + " ordered=" + ordered);
11186 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011187 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011188 }
11189
11190 // Handle special intents: if this broadcast is from the package
11191 // manager about a package being removed, we need to remove all of
11192 // its activities from the history stack.
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011193 final boolean uidRemoved = Intent.ACTION_UID_REMOVED.equals(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011194 intent.getAction());
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011195 if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
11196 || Intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080011197 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011198 || uidRemoved) {
11199 if (checkComponentPermission(
11200 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011201 callingPid, callingUid, -1, true)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011202 == PackageManager.PERMISSION_GRANTED) {
11203 if (uidRemoved) {
11204 final Bundle intentExtras = intent.getExtras();
11205 final int uid = intentExtras != null
11206 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
11207 if (uid >= 0) {
11208 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
11209 synchronized (bs) {
11210 bs.removeUidStatsLocked(uid);
11211 }
11212 }
11213 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011214 // If resources are unvailble just force stop all
11215 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080011216 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011217 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
11218 if (list != null && (list.length > 0)) {
11219 for (String pkg : list) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011220 forceStopPackageLocked(pkg, -1, false, true, true);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011221 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070011222 sendPackageBroadcastLocked(
11223 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011224 }
11225 } else {
11226 Uri data = intent.getData();
11227 String ssp;
11228 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
11229 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
11230 forceStopPackageLocked(ssp,
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080011231 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070011232 }
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011233 if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070011234 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
11235 new String[] {ssp});
11236 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011237 }
11238 }
11239 }
11240 } else {
11241 String msg = "Permission Denial: " + intent.getAction()
11242 + " broadcast from " + callerPackage + " (pid=" + callingPid
11243 + ", uid=" + callingUid + ")"
11244 + " requires "
11245 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011246 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011247 throw new SecurityException(msg);
11248 }
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011249
11250 // Special case for adding a package: by default turn on compatibility
11251 // mode.
11252 } else if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())) {
Dianne Hackborn8ea5e1d2011-05-27 16:45:31 -070011253 Uri data = intent.getData();
11254 String ssp;
11255 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
11256 mCompatModePackages.handlePackageAddedLocked(ssp,
11257 intent.getBooleanExtra(Intent.EXTRA_REPLACING, false));
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011258 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011259 }
11260
11261 /*
11262 * If this is the time zone changed action, queue up a message that will reset the timezone
11263 * of all currently running processes. This message will get queued up before the broadcast
11264 * happens.
11265 */
11266 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
11267 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
11268 }
11269
Robert Greenwalt03595d02010-11-02 14:08:23 -070011270 if (intent.ACTION_CLEAR_DNS_CACHE.equals(intent.getAction())) {
11271 mHandler.sendEmptyMessage(CLEAR_DNS_CACHE);
11272 }
11273
Robert Greenwalt434203a2010-10-11 16:00:27 -070011274 if (Proxy.PROXY_CHANGE_ACTION.equals(intent.getAction())) {
11275 ProxyProperties proxy = intent.getParcelableExtra("proxy");
11276 mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY, proxy));
11277 }
11278
Dianne Hackborn854060af2009-07-09 18:14:31 -070011279 /*
11280 * Prevent non-system code (defined here to be non-persistent
11281 * processes) from sending protected broadcasts.
11282 */
11283 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
11284 || callingUid == Process.SHELL_UID || callingUid == 0) {
11285 // Always okay.
11286 } else if (callerApp == null || !callerApp.persistent) {
11287 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011288 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -070011289 intent.getAction())) {
11290 String msg = "Permission Denial: not allowed to send broadcast "
11291 + intent.getAction() + " from pid="
11292 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011293 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070011294 throw new SecurityException(msg);
11295 }
11296 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011297 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070011298 return BROADCAST_SUCCESS;
11299 }
11300 }
11301
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011302 // Add to the sticky list if requested.
11303 if (sticky) {
11304 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
11305 callingPid, callingUid)
11306 != PackageManager.PERMISSION_GRANTED) {
11307 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
11308 + callingPid + ", uid=" + callingUid
11309 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011310 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011311 throw new SecurityException(msg);
11312 }
11313 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011314 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011315 + " and enforce permission " + requiredPermission);
11316 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
11317 }
11318 if (intent.getComponent() != null) {
11319 throw new SecurityException(
11320 "Sticky broadcasts can't target a specific component");
11321 }
11322 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
11323 if (list == null) {
11324 list = new ArrayList<Intent>();
11325 mStickyBroadcasts.put(intent.getAction(), list);
11326 }
11327 int N = list.size();
11328 int i;
11329 for (i=0; i<N; i++) {
11330 if (intent.filterEquals(list.get(i))) {
11331 // This sticky already exists, replace it.
11332 list.set(i, new Intent(intent));
11333 break;
11334 }
11335 }
11336 if (i >= N) {
11337 list.add(new Intent(intent));
11338 }
11339 }
11340
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011341 // Figure out who all will receive this broadcast.
11342 List receivers = null;
11343 List<BroadcastFilter> registeredReceivers = null;
11344 try {
11345 if (intent.getComponent() != null) {
11346 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011347 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070011348 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011349 if (ai != null) {
11350 receivers = new ArrayList();
11351 ResolveInfo ri = new ResolveInfo();
11352 ri.activityInfo = ai;
11353 receivers.add(ri);
11354 }
11355 } else {
11356 // Need to resolve the intent to interested receivers...
11357 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
11358 == 0) {
11359 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011360 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011361 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011362 }
Mihai Preda074edef2009-05-18 17:13:31 +020011363 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011364 }
11365 } catch (RemoteException ex) {
11366 // pm is in same process, this will never happen.
11367 }
11368
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011369 final boolean replacePending =
11370 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
11371
Joe Onorato8a9b2202010-02-26 18:56:32 -080011372 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011373 + " replacePending=" + replacePending);
11374
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011375 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
11376 if (!ordered && NR > 0) {
11377 // If we are not serializing this broadcast, then send the
11378 // registered receivers separately so they don't wait for the
11379 // components to be launched.
11380 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
11381 callerPackage, callingPid, callingUid, requiredPermission,
11382 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011383 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011384 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011385 TAG, "Enqueueing parallel broadcast " + r
11386 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011387 boolean replaced = false;
11388 if (replacePending) {
11389 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
11390 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011391 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011392 "***** DROPPING PARALLEL: " + intent);
11393 mParallelBroadcasts.set(i, r);
11394 replaced = true;
11395 break;
11396 }
11397 }
11398 }
11399 if (!replaced) {
11400 mParallelBroadcasts.add(r);
11401 scheduleBroadcastsLocked();
11402 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011403 registeredReceivers = null;
11404 NR = 0;
11405 }
11406
11407 // Merge into one list.
11408 int ir = 0;
11409 if (receivers != null) {
11410 // A special case for PACKAGE_ADDED: do not allow the package
11411 // being added to see this broadcast. This prevents them from
11412 // using this as a back door to get run as soon as they are
11413 // installed. Maybe in the future we want to have a special install
11414 // broadcast or such for apps, but we'd like to deliberately make
11415 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011416 String skipPackages[] = null;
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011417 if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
11418 || Intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
11419 || Intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011420 Uri data = intent.getData();
11421 if (data != null) {
11422 String pkgName = data.getSchemeSpecificPart();
11423 if (pkgName != null) {
11424 skipPackages = new String[] { pkgName };
11425 }
11426 }
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011427 } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011428 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070011429 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011430 if (skipPackages != null && (skipPackages.length > 0)) {
11431 for (String skipPackage : skipPackages) {
11432 if (skipPackage != null) {
11433 int NT = receivers.size();
11434 for (int it=0; it<NT; it++) {
11435 ResolveInfo curt = (ResolveInfo)receivers.get(it);
11436 if (curt.activityInfo.packageName.equals(skipPackage)) {
11437 receivers.remove(it);
11438 it--;
11439 NT--;
11440 }
11441 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011442 }
11443 }
11444 }
11445
11446 int NT = receivers != null ? receivers.size() : 0;
11447 int it = 0;
11448 ResolveInfo curt = null;
11449 BroadcastFilter curr = null;
11450 while (it < NT && ir < NR) {
11451 if (curt == null) {
11452 curt = (ResolveInfo)receivers.get(it);
11453 }
11454 if (curr == null) {
11455 curr = registeredReceivers.get(ir);
11456 }
11457 if (curr.getPriority() >= curt.priority) {
11458 // Insert this broadcast record into the final list.
11459 receivers.add(it, curr);
11460 ir++;
11461 curr = null;
11462 it++;
11463 NT++;
11464 } else {
11465 // Skip to the next ResolveInfo in the final list.
11466 it++;
11467 curt = null;
11468 }
11469 }
11470 }
11471 while (ir < NR) {
11472 if (receivers == null) {
11473 receivers = new ArrayList();
11474 }
11475 receivers.add(registeredReceivers.get(ir));
11476 ir++;
11477 }
11478
11479 if ((receivers != null && receivers.size() > 0)
11480 || resultTo != null) {
11481 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
11482 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011483 receivers, resultTo, resultCode, resultData, map, ordered,
11484 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011485 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011486 TAG, "Enqueueing ordered broadcast " + r
11487 + ": prev had " + mOrderedBroadcasts.size());
11488 if (DEBUG_BROADCAST) {
11489 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011490 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011491 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011492 boolean replaced = false;
11493 if (replacePending) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011494 for (int i=mOrderedBroadcasts.size()-1; i>0; i--) {
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011495 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011496 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011497 "***** DROPPING ORDERED: " + intent);
11498 mOrderedBroadcasts.set(i, r);
11499 replaced = true;
11500 break;
11501 }
11502 }
11503 }
11504 if (!replaced) {
11505 mOrderedBroadcasts.add(r);
11506 scheduleBroadcastsLocked();
11507 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011508 }
11509
11510 return BROADCAST_SUCCESS;
11511 }
11512
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011513 final Intent verifyBroadcastLocked(Intent intent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011514 // Refuse possible leaked file descriptors
11515 if (intent != null && intent.hasFileDescriptors() == true) {
11516 throw new IllegalArgumentException("File descriptors passed in Intent");
11517 }
11518
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011519 int flags = intent.getFlags();
11520
11521 if (!mProcessesReady) {
11522 // if the caller really truly claims to know what they're doing, go
11523 // ahead and allow the broadcast without launching any receivers
11524 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
11525 intent = new Intent(intent);
11526 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
11527 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
11528 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
11529 + " before boot completion");
11530 throw new IllegalStateException("Cannot broadcast before boot completed");
11531 }
11532 }
11533
11534 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
11535 throw new IllegalArgumentException(
11536 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
11537 }
11538
11539 return intent;
11540 }
11541
11542 public final int broadcastIntent(IApplicationThread caller,
11543 Intent intent, String resolvedType, IIntentReceiver resultTo,
11544 int resultCode, String resultData, Bundle map,
11545 String requiredPermission, boolean serialized, boolean sticky) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011546 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011547 intent = verifyBroadcastLocked(intent);
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011548
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011549 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11550 final int callingPid = Binder.getCallingPid();
11551 final int callingUid = Binder.getCallingUid();
11552 final long origId = Binder.clearCallingIdentity();
11553 int res = broadcastIntentLocked(callerApp,
11554 callerApp != null ? callerApp.info.packageName : null,
11555 intent, resolvedType, resultTo,
11556 resultCode, resultData, map, requiredPermission, serialized,
11557 sticky, callingPid, callingUid);
11558 Binder.restoreCallingIdentity(origId);
11559 return res;
11560 }
11561 }
11562
11563 int broadcastIntentInPackage(String packageName, int uid,
11564 Intent intent, String resolvedType, IIntentReceiver resultTo,
11565 int resultCode, String resultData, Bundle map,
11566 String requiredPermission, boolean serialized, boolean sticky) {
11567 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011568 intent = verifyBroadcastLocked(intent);
11569
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011570 final long origId = Binder.clearCallingIdentity();
11571 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
11572 resultTo, resultCode, resultData, map, requiredPermission,
11573 serialized, sticky, -1, uid);
11574 Binder.restoreCallingIdentity(origId);
11575 return res;
11576 }
11577 }
11578
11579 public final void unbroadcastIntent(IApplicationThread caller,
11580 Intent intent) {
11581 // Refuse possible leaked file descriptors
11582 if (intent != null && intent.hasFileDescriptors() == true) {
11583 throw new IllegalArgumentException("File descriptors passed in Intent");
11584 }
11585
11586 synchronized(this) {
11587 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
11588 != PackageManager.PERMISSION_GRANTED) {
11589 String msg = "Permission Denial: unbroadcastIntent() from pid="
11590 + Binder.getCallingPid()
11591 + ", uid=" + Binder.getCallingUid()
11592 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011593 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011594 throw new SecurityException(msg);
11595 }
11596 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
11597 if (list != null) {
11598 int N = list.size();
11599 int i;
11600 for (i=0; i<N; i++) {
11601 if (intent.filterEquals(list.get(i))) {
11602 list.remove(i);
11603 break;
11604 }
11605 }
11606 }
11607 }
11608 }
11609
11610 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
11611 String resultData, Bundle resultExtras, boolean resultAbort,
11612 boolean explicit) {
11613 if (mOrderedBroadcasts.size() == 0) {
11614 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011615 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011616 }
11617 return false;
11618 }
11619 BroadcastRecord r = mOrderedBroadcasts.get(0);
11620 if (r.receiver == null) {
11621 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011622 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011623 }
11624 return false;
11625 }
11626 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011627 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011628 return false;
11629 }
11630 int state = r.state;
Dianne Hackbornce86ba82011-07-13 19:33:41 -070011631 r.state = BroadcastRecord.IDLE;
11632 if (state == BroadcastRecord.IDLE) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011633 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011634 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011635 }
11636 }
11637 r.receiver = null;
11638 r.intent.setComponent(null);
11639 if (r.curApp != null) {
11640 r.curApp.curReceiver = null;
11641 }
11642 if (r.curFilter != null) {
11643 r.curFilter.receiverList.curBroadcast = null;
11644 }
11645 r.curFilter = null;
11646 r.curApp = null;
11647 r.curComponent = null;
11648 r.curReceiver = null;
11649 mPendingBroadcast = null;
11650
11651 r.resultCode = resultCode;
11652 r.resultData = resultData;
11653 r.resultExtras = resultExtras;
11654 r.resultAbort = resultAbort;
11655
11656 // We will process the next receiver right now if this is finishing
11657 // an app receiver (which is always asynchronous) or after we have
11658 // come back from calling a receiver.
11659 return state == BroadcastRecord.APP_RECEIVE
11660 || state == BroadcastRecord.CALL_DONE_RECEIVE;
11661 }
11662
11663 public void finishReceiver(IBinder who, int resultCode, String resultData,
11664 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011665 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011666
11667 // Refuse possible leaked file descriptors
11668 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
11669 throw new IllegalArgumentException("File descriptors passed in Bundle");
11670 }
11671
11672 boolean doNext;
11673
11674 final long origId = Binder.clearCallingIdentity();
11675
11676 synchronized(this) {
11677 doNext = finishReceiverLocked(
11678 who, resultCode, resultData, resultExtras, resultAbort, true);
11679 }
11680
11681 if (doNext) {
11682 processNextBroadcast(false);
11683 }
11684 trimApplications();
11685
11686 Binder.restoreCallingIdentity(origId);
11687 }
11688
Jeff Brown4d94a762010-09-23 11:33:28 -070011689 private final void logBroadcastReceiverDiscardLocked(BroadcastRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011690 if (r.nextReceiver > 0) {
11691 Object curReceiver = r.receivers.get(r.nextReceiver-1);
11692 if (curReceiver instanceof BroadcastFilter) {
11693 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080011694 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011695 System.identityHashCode(r),
11696 r.intent.getAction(),
11697 r.nextReceiver - 1,
11698 System.identityHashCode(bf));
11699 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080011700 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011701 System.identityHashCode(r),
11702 r.intent.getAction(),
11703 r.nextReceiver - 1,
11704 ((ResolveInfo)curReceiver).toString());
11705 }
11706 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011707 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011708 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011709 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011710 System.identityHashCode(r),
11711 r.intent.getAction(),
11712 r.nextReceiver,
11713 "NONE");
11714 }
11715 }
11716
Jeff Brown4d94a762010-09-23 11:33:28 -070011717 private final void setBroadcastTimeoutLocked(long timeoutTime) {
11718 if (! mPendingBroadcastTimeoutMessage) {
11719 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
11720 mHandler.sendMessageAtTime(msg, timeoutTime);
11721 mPendingBroadcastTimeoutMessage = true;
11722 }
11723 }
11724
11725 private final void cancelBroadcastTimeoutLocked() {
11726 if (mPendingBroadcastTimeoutMessage) {
11727 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
11728 mPendingBroadcastTimeoutMessage = false;
11729 }
11730 }
11731
11732 private final void broadcastTimeoutLocked(boolean fromMsg) {
11733 if (fromMsg) {
11734 mPendingBroadcastTimeoutMessage = false;
11735 }
11736
11737 if (mOrderedBroadcasts.size() == 0) {
11738 return;
11739 }
11740
11741 long now = SystemClock.uptimeMillis();
11742 BroadcastRecord r = mOrderedBroadcasts.get(0);
11743 if (fromMsg) {
11744 if (mDidDexOpt) {
11745 // Delay timeouts until dexopt finishes.
11746 mDidDexOpt = false;
11747 long timeoutTime = SystemClock.uptimeMillis() + BROADCAST_TIMEOUT;
11748 setBroadcastTimeoutLocked(timeoutTime);
11749 return;
11750 }
11751 if (! mProcessesReady) {
11752 // Only process broadcast timeouts if the system is ready. That way
11753 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
11754 // to do heavy lifting for system up.
11755 return;
11756 }
11757
11758 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
11759 if (timeoutTime > now) {
11760 // We can observe premature timeouts because we do not cancel and reset the
11761 // broadcast timeout message after each receiver finishes. Instead, we set up
11762 // an initial timeout then kick it down the road a little further as needed
11763 // when it expires.
11764 if (DEBUG_BROADCAST) Slog.v(TAG,
11765 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
11766 + timeoutTime);
11767 setBroadcastTimeoutLocked(timeoutTime);
11768 return;
11769 }
11770 }
11771
11772 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver
11773 + ", started " + (now - r.receiverTime) + "ms ago");
11774 r.receiverTime = now;
11775 r.anrCount++;
11776
11777 // Current receiver has passed its expiration date.
11778 if (r.nextReceiver <= 0) {
11779 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
11780 return;
11781 }
11782
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011783 ProcessRecord app = null;
11784 String anrMessage = null;
11785
Jeff Brown4d94a762010-09-23 11:33:28 -070011786 Object curReceiver = r.receivers.get(r.nextReceiver-1);
11787 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
11788 logBroadcastReceiverDiscardLocked(r);
11789 if (curReceiver instanceof BroadcastFilter) {
11790 BroadcastFilter bf = (BroadcastFilter)curReceiver;
11791 if (bf.receiverList.pid != 0
11792 && bf.receiverList.pid != MY_PID) {
11793 synchronized (this.mPidsSelfLocked) {
11794 app = this.mPidsSelfLocked.get(
11795 bf.receiverList.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011796 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011797 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011798 } else {
11799 app = r.curApp;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011800 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011801
Jeff Brown4d94a762010-09-23 11:33:28 -070011802 if (app != null) {
11803 anrMessage = "Broadcast of " + r.intent.toString();
11804 }
11805
11806 if (mPendingBroadcast == r) {
11807 mPendingBroadcast = null;
11808 }
11809
11810 // Move on to the next receiver.
11811 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
11812 r.resultExtras, r.resultAbort, true);
11813 scheduleBroadcastsLocked();
11814
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011815 if (anrMessage != null) {
Jeff Brown4d94a762010-09-23 11:33:28 -070011816 // Post the ANR to the handler since we do not want to process ANRs while
11817 // potentially holding our lock.
11818 mHandler.post(new AppNotResponding(app, anrMessage));
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011819 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011820 }
11821
11822 private final void processCurBroadcastLocked(BroadcastRecord r,
11823 ProcessRecord app) throws RemoteException {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011824 if (DEBUG_BROADCAST) Slog.v(TAG,
11825 "Process cur broadcast " + r + " for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011826 if (app.thread == null) {
11827 throw new RemoteException();
11828 }
11829 r.receiver = app.thread.asBinder();
11830 r.curApp = app;
11831 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011832 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011833
11834 // Tell the application to launch this receiver.
11835 r.intent.setComponent(r.curComponent);
11836
11837 boolean started = false;
11838 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011839 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011840 "Delivering to component " + r.curComponent
11841 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070011842 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011843 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
Dianne Hackborne2515ee2011-04-27 18:52:56 -040011844 compatibilityInfoForPackageLocked(r.curReceiver.applicationInfo),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011845 r.resultCode, r.resultData, r.resultExtras, r.ordered);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011846 if (DEBUG_BROADCAST) Slog.v(TAG,
11847 "Process cur broadcast " + r + " DELIVERED for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011848 started = true;
11849 } finally {
11850 if (!started) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011851 if (DEBUG_BROADCAST) Slog.v(TAG,
11852 "Process cur broadcast " + r + ": NOT STARTED!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011853 r.receiver = null;
11854 r.curApp = null;
11855 app.curReceiver = null;
11856 }
11857 }
11858
11859 }
11860
Jeff Brown4d94a762010-09-23 11:33:28 -070011861 static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011862 Intent intent, int resultCode, String data, Bundle extras,
11863 boolean ordered, boolean sticky) throws RemoteException {
Jeff Brown4d94a762010-09-23 11:33:28 -070011864 // Send the intent to the receiver asynchronously using one-way binder calls.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011865 if (app != null && app.thread != null) {
11866 // If we have an app thread, do the call through that so it is
11867 // correctly ordered with other one-way calls.
11868 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011869 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011870 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070011871 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011872 }
11873 }
11874
Jeff Brown4d94a762010-09-23 11:33:28 -070011875 private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011876 BroadcastFilter filter, boolean ordered) {
11877 boolean skip = false;
11878 if (filter.requiredPermission != null) {
11879 int perm = checkComponentPermission(filter.requiredPermission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011880 r.callingPid, r.callingUid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011881 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011882 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011883 + r.intent.toString()
11884 + " from " + r.callerPackage + " (pid="
11885 + r.callingPid + ", uid=" + r.callingUid + ")"
11886 + " requires " + filter.requiredPermission
11887 + " due to registered receiver " + filter);
11888 skip = true;
11889 }
11890 }
11891 if (r.requiredPermission != null) {
11892 int perm = checkComponentPermission(r.requiredPermission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011893 filter.receiverList.pid, filter.receiverList.uid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011894 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011895 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011896 + r.intent.toString()
11897 + " to " + filter.receiverList.app
11898 + " (pid=" + filter.receiverList.pid
11899 + ", uid=" + filter.receiverList.uid + ")"
11900 + " requires " + r.requiredPermission
11901 + " due to sender " + r.callerPackage
11902 + " (uid " + r.callingUid + ")");
11903 skip = true;
11904 }
11905 }
11906
11907 if (!skip) {
11908 // If this is not being sent as an ordered broadcast, then we
11909 // don't want to touch the fields that keep track of the current
11910 // state of ordered broadcasts.
11911 if (ordered) {
11912 r.receiver = filter.receiverList.receiver.asBinder();
11913 r.curFilter = filter;
11914 filter.receiverList.curBroadcast = r;
11915 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011916 if (filter.receiverList.app != null) {
11917 // Bump hosting application to no longer be in background
11918 // scheduling class. Note that we can't do that if there
11919 // isn't an app... but we can only be in that case for
11920 // things that directly call the IActivityManager API, which
11921 // are already core system stuff so don't matter for this.
11922 r.curApp = filter.receiverList.app;
11923 filter.receiverList.app.curReceiver = r;
11924 updateOomAdjLocked();
11925 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011926 }
11927 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011928 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011929 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011930 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011931 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011932 }
Jeff Brown4d94a762010-09-23 11:33:28 -070011933 performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011934 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011935 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011936 if (ordered) {
11937 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
11938 }
11939 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011940 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011941 if (ordered) {
11942 r.receiver = null;
11943 r.curFilter = null;
11944 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011945 if (filter.receiverList.app != null) {
11946 filter.receiverList.app.curReceiver = null;
11947 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011948 }
11949 }
11950 }
11951 }
11952
Dianne Hackborn12527f92009-11-11 17:39:50 -080011953 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
11954 if (r.callingUid < 0) {
11955 // This was from a registerReceiver() call; ignore it.
11956 return;
11957 }
11958 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
11959 MAX_BROADCAST_HISTORY-1);
11960 r.finishTime = SystemClock.uptimeMillis();
11961 mBroadcastHistory[0] = r;
11962 }
11963
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011964 private final void processNextBroadcast(boolean fromMsg) {
11965 synchronized(this) {
11966 BroadcastRecord r;
11967
Joe Onorato8a9b2202010-02-26 18:56:32 -080011968 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011969 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011970 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011971
11972 updateCpuStats();
11973
11974 if (fromMsg) {
11975 mBroadcastsScheduled = false;
11976 }
11977
11978 // First, deliver any non-serialized broadcasts right away.
11979 while (mParallelBroadcasts.size() > 0) {
11980 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080011981 r.dispatchTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011982 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011983 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011984 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011985 for (int i=0; i<N; i++) {
11986 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011987 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070011988 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011989 + target + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070011990 deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011991 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080011992 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011993 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070011994 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011995 }
11996
11997 // Now take care of the next serialized one...
11998
11999 // If we are waiting for a process to come up to handle the next
12000 // broadcast, then do nothing at this point. Just in case, we
12001 // check that the process we're waiting for still exists.
12002 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070012003 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012004 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070012005 + mPendingBroadcast.curApp);
12006 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012007
12008 boolean isDead;
12009 synchronized (mPidsSelfLocked) {
12010 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
12011 }
12012 if (!isDead) {
12013 // It's still alive, so keep waiting
12014 return;
12015 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012016 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012017 + " died before responding to broadcast");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012018 mPendingBroadcast.state = BroadcastRecord.IDLE;
12019 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012020 mPendingBroadcast = null;
12021 }
12022 }
12023
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012024 boolean looped = false;
12025
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012026 do {
12027 if (mOrderedBroadcasts.size() == 0) {
12028 // No more broadcasts pending, so all done!
12029 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012030 if (looped) {
12031 // If we had finished the last ordered broadcast, then
12032 // make sure all processes have correct oom and sched
12033 // adjustments.
12034 updateOomAdjLocked();
12035 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012036 return;
12037 }
12038 r = mOrderedBroadcasts.get(0);
12039 boolean forceReceive = false;
12040
12041 // Ensure that even if something goes awry with the timeout
12042 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050012043 // and continue to make progress.
12044 //
12045 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
Jeff Brown4d94a762010-09-23 11:33:28 -070012046 // receivers don't get executed with timeouts. They're intended for
Jeff Hamiltonacf84742010-05-25 22:10:18 -050012047 // one time heavy lifting after system upgrades and can take
12048 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012049 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012050 if (mProcessesReady && r.dispatchTime > 0) {
Jeff Hamiltonacf84742010-05-25 22:10:18 -050012051 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012052 if ((numReceivers > 0) &&
12053 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012054 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012055 + " now=" + now
12056 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080012057 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012058 + " intent=" + r.intent
12059 + " numReceivers=" + numReceivers
12060 + " nextReceiver=" + r.nextReceiver
12061 + " state=" + r.state);
Jeff Brown4d94a762010-09-23 11:33:28 -070012062 broadcastTimeoutLocked(false); // forcibly finish this broadcast
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012063 forceReceive = true;
12064 r.state = BroadcastRecord.IDLE;
12065 }
12066 }
12067
12068 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012069 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012070 "processNextBroadcast() called when not idle (state="
12071 + r.state + ")");
12072 return;
12073 }
12074
12075 if (r.receivers == null || r.nextReceiver >= numReceivers
12076 || r.resultAbort || forceReceive) {
12077 // No more receivers for this broadcast! Send the final
12078 // result if requested...
12079 if (r.resultTo != null) {
12080 try {
12081 if (DEBUG_BROADCAST) {
12082 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012083 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012084 + " seq=" + seq + " app=" + r.callerApp);
12085 }
Jeff Brown4d94a762010-09-23 11:33:28 -070012086 performReceiveLocked(r.callerApp, r.resultTo,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012087 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012088 r.resultData, r.resultExtras, false, false);
Johannes Carlssonb5a86542010-10-27 10:08:10 +020012089 // Set this to null so that the reference
12090 // (local and remote) isnt kept in the mBroadcastHistory.
12091 r.resultTo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012092 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012093 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012094 }
12095 }
12096
Joe Onorato8a9b2202010-02-26 18:56:32 -080012097 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
Jeff Brown4d94a762010-09-23 11:33:28 -070012098 cancelBroadcastTimeoutLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012099
Joe Onorato8a9b2202010-02-26 18:56:32 -080012100 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012101 + r);
12102
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012103 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080012104 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012105 mOrderedBroadcasts.remove(0);
12106 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012107 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012108 continue;
12109 }
12110 } while (r == null);
12111
12112 // Get the next receiver...
12113 int recIdx = r.nextReceiver++;
12114
12115 // Keep track of when this receiver started, and make sure there
12116 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080012117 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012118 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080012119 r.dispatchTime = r.receiverTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012120
Joe Onorato8a9b2202010-02-26 18:56:32 -080012121 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012122 + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070012123 }
12124 if (! mPendingBroadcastTimeoutMessage) {
12125 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012126 if (DEBUG_BROADCAST) Slog.v(TAG,
Jeff Brown4d94a762010-09-23 11:33:28 -070012127 "Submitting BROADCAST_TIMEOUT_MSG for " + r + " at " + timeoutTime);
12128 setBroadcastTimeoutLocked(timeoutTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012129 }
12130
12131 Object nextReceiver = r.receivers.get(recIdx);
12132 if (nextReceiver instanceof BroadcastFilter) {
12133 // Simple case: this is a registered receiver who gets
12134 // a direct call.
12135 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012136 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070012137 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012138 + filter + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070012139 deliverToRegisteredReceiverLocked(r, filter, r.ordered);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012140 if (r.receiver == null || !r.ordered) {
12141 // The receiver has already finished, so schedule to
12142 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070012143 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
12144 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012145 r.state = BroadcastRecord.IDLE;
12146 scheduleBroadcastsLocked();
12147 }
12148 return;
12149 }
12150
12151 // Hard case: need to instantiate the receiver, possibly
12152 // starting its application process to host it.
12153
12154 ResolveInfo info =
12155 (ResolveInfo)nextReceiver;
12156
12157 boolean skip = false;
12158 int perm = checkComponentPermission(info.activityInfo.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080012159 r.callingPid, r.callingUid, info.activityInfo.applicationInfo.uid,
12160 info.activityInfo.exported);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012161 if (perm != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080012162 if (!info.activityInfo.exported) {
12163 Slog.w(TAG, "Permission Denial: broadcasting "
12164 + r.intent.toString()
12165 + " from " + r.callerPackage + " (pid=" + r.callingPid
12166 + ", uid=" + r.callingUid + ")"
12167 + " is not exported from uid " + info.activityInfo.applicationInfo.uid
12168 + " due to receiver " + info.activityInfo.packageName
12169 + "/" + info.activityInfo.name);
12170 } else {
12171 Slog.w(TAG, "Permission Denial: broadcasting "
12172 + r.intent.toString()
12173 + " from " + r.callerPackage + " (pid=" + r.callingPid
12174 + ", uid=" + r.callingUid + ")"
12175 + " requires " + info.activityInfo.permission
12176 + " due to receiver " + info.activityInfo.packageName
12177 + "/" + info.activityInfo.name);
12178 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012179 skip = true;
12180 }
12181 if (r.callingUid != Process.SYSTEM_UID &&
12182 r.requiredPermission != null) {
12183 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012184 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012185 checkPermission(r.requiredPermission,
12186 info.activityInfo.applicationInfo.packageName);
12187 } catch (RemoteException e) {
12188 perm = PackageManager.PERMISSION_DENIED;
12189 }
12190 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012191 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012192 + r.intent + " to "
12193 + info.activityInfo.applicationInfo.packageName
12194 + " requires " + r.requiredPermission
12195 + " due to sender " + r.callerPackage
12196 + " (uid " + r.callingUid + ")");
12197 skip = true;
12198 }
12199 }
12200 if (r.curApp != null && r.curApp.crashing) {
12201 // If the target process is crashing, just skip it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012202 if (DEBUG_BROADCAST) Slog.v(TAG,
12203 "Skipping deliver ordered " + r + " to " + r.curApp
12204 + ": process crashing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012205 skip = true;
12206 }
12207
12208 if (skip) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012209 if (DEBUG_BROADCAST) Slog.v(TAG,
12210 "Skipping delivery of ordered " + r + " for whatever reason");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012211 r.receiver = null;
12212 r.curFilter = null;
12213 r.state = BroadcastRecord.IDLE;
12214 scheduleBroadcastsLocked();
12215 return;
12216 }
12217
12218 r.state = BroadcastRecord.APP_RECEIVE;
12219 String targetProcess = info.activityInfo.processName;
12220 r.curComponent = new ComponentName(
12221 info.activityInfo.applicationInfo.packageName,
12222 info.activityInfo.name);
12223 r.curReceiver = info.activityInfo;
12224
Dianne Hackborne7f97212011-02-24 14:40:20 -080012225 // Broadcast is being executed, its package can't be stopped.
12226 try {
12227 AppGlobals.getPackageManager().setPackageStoppedState(
12228 r.curComponent.getPackageName(), false);
12229 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -080012230 } catch (IllegalArgumentException e) {
12231 Slog.w(TAG, "Failed trying to unstop package "
12232 + r.curComponent.getPackageName() + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -080012233 }
12234
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012235 // Is this receiver's application already running?
12236 ProcessRecord app = getProcessRecordLocked(targetProcess,
12237 info.activityInfo.applicationInfo.uid);
12238 if (app != null && app.thread != null) {
12239 try {
Dianne Hackborn6c418d52011-06-29 14:05:33 -070012240 app.addPackage(info.activityInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012241 processCurBroadcastLocked(r, app);
12242 return;
12243 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012244 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012245 + r.curComponent, e);
12246 }
12247
12248 // If a dead object exception was thrown -- fall through to
12249 // restart the application.
12250 }
12251
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012252 // Not running -- get it started, to be executed when the app comes up.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012253 if (DEBUG_BROADCAST) Slog.v(TAG,
12254 "Need to start app " + targetProcess + " for broadcast " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012255 if ((r.curApp=startProcessLocked(targetProcess,
12256 info.activityInfo.applicationInfo, true,
12257 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012258 "broadcast", r.curComponent,
12259 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
12260 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012261 // Ah, this recipient is unavailable. Finish it if necessary,
12262 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012263 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012264 + info.activityInfo.applicationInfo.packageName + "/"
12265 + info.activityInfo.applicationInfo.uid + " for broadcast "
12266 + r.intent + ": process is bad");
Jeff Brown4d94a762010-09-23 11:33:28 -070012267 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012268 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
12269 r.resultExtras, r.resultAbort, true);
12270 scheduleBroadcastsLocked();
12271 r.state = BroadcastRecord.IDLE;
12272 return;
12273 }
12274
12275 mPendingBroadcast = r;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012276 mPendingBroadcastRecvIndex = recIdx;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012277 }
12278 }
12279
12280 // =========================================================
12281 // INSTRUMENTATION
12282 // =========================================================
12283
12284 public boolean startInstrumentation(ComponentName className,
12285 String profileFile, int flags, Bundle arguments,
12286 IInstrumentationWatcher watcher) {
12287 // Refuse possible leaked file descriptors
12288 if (arguments != null && arguments.hasFileDescriptors()) {
12289 throw new IllegalArgumentException("File descriptors passed in Bundle");
12290 }
12291
12292 synchronized(this) {
12293 InstrumentationInfo ii = null;
12294 ApplicationInfo ai = null;
12295 try {
12296 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012297 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012298 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012299 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012300 } catch (PackageManager.NameNotFoundException e) {
12301 }
12302 if (ii == null) {
12303 reportStartInstrumentationFailure(watcher, className,
12304 "Unable to find instrumentation info for: " + className);
12305 return false;
12306 }
12307 if (ai == null) {
12308 reportStartInstrumentationFailure(watcher, className,
12309 "Unable to find instrumentation target package: " + ii.targetPackage);
12310 return false;
12311 }
12312
12313 int match = mContext.getPackageManager().checkSignatures(
12314 ii.targetPackage, ii.packageName);
12315 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
12316 String msg = "Permission Denial: starting instrumentation "
12317 + className + " from pid="
12318 + Binder.getCallingPid()
12319 + ", uid=" + Binder.getCallingPid()
12320 + " not allowed because package " + ii.packageName
12321 + " does not have a signature matching the target "
12322 + ii.targetPackage;
12323 reportStartInstrumentationFailure(watcher, className, msg);
12324 throw new SecurityException(msg);
12325 }
12326
12327 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012328 forceStopPackageLocked(ii.targetPackage, -1, true, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012329 ProcessRecord app = addAppLocked(ai);
12330 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070012331 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012332 app.instrumentationProfileFile = profileFile;
12333 app.instrumentationArguments = arguments;
12334 app.instrumentationWatcher = watcher;
12335 app.instrumentationResultClass = className;
12336 Binder.restoreCallingIdentity(origId);
12337 }
12338
12339 return true;
12340 }
12341
12342 /**
12343 * Report errors that occur while attempting to start Instrumentation. Always writes the
12344 * error to the logs, but if somebody is watching, send the report there too. This enables
12345 * the "am" command to report errors with more information.
12346 *
12347 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
12348 * @param cn The component name of the instrumentation.
12349 * @param report The error report.
12350 */
12351 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
12352 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012353 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012354 try {
12355 if (watcher != null) {
12356 Bundle results = new Bundle();
12357 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
12358 results.putString("Error", report);
12359 watcher.instrumentationStatus(cn, -1, results);
12360 }
12361 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012362 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012363 }
12364 }
12365
12366 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
12367 if (app.instrumentationWatcher != null) {
12368 try {
12369 // NOTE: IInstrumentationWatcher *must* be oneway here
12370 app.instrumentationWatcher.instrumentationFinished(
12371 app.instrumentationClass,
12372 resultCode,
12373 results);
12374 } catch (RemoteException e) {
12375 }
12376 }
12377 app.instrumentationWatcher = null;
12378 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070012379 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012380 app.instrumentationProfileFile = null;
12381 app.instrumentationArguments = null;
12382
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080012383 forceStopPackageLocked(app.processName, -1, false, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012384 }
12385
12386 public void finishInstrumentation(IApplicationThread target,
12387 int resultCode, Bundle results) {
12388 // Refuse possible leaked file descriptors
12389 if (results != null && results.hasFileDescriptors()) {
12390 throw new IllegalArgumentException("File descriptors passed in Intent");
12391 }
12392
12393 synchronized(this) {
12394 ProcessRecord app = getRecordForAppLocked(target);
12395 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012396 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012397 return;
12398 }
12399 final long origId = Binder.clearCallingIdentity();
12400 finishInstrumentationLocked(app, resultCode, results);
12401 Binder.restoreCallingIdentity(origId);
12402 }
12403 }
12404
12405 // =========================================================
12406 // CONFIGURATION
12407 // =========================================================
12408
12409 public ConfigurationInfo getDeviceConfigurationInfo() {
12410 ConfigurationInfo config = new ConfigurationInfo();
12411 synchronized (this) {
12412 config.reqTouchScreen = mConfiguration.touchscreen;
12413 config.reqKeyboardType = mConfiguration.keyboard;
12414 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070012415 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
12416 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012417 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
12418 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070012419 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
12420 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012421 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
12422 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070012423 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012424 }
12425 return config;
12426 }
12427
12428 public Configuration getConfiguration() {
12429 Configuration ci;
12430 synchronized(this) {
12431 ci = new Configuration(mConfiguration);
12432 }
12433 return ci;
12434 }
12435
Dianne Hackborn31ca8542011-07-19 14:58:28 -070012436 public void updatePersistentConfiguration(Configuration values) {
12437 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
12438 "updateConfiguration()");
12439 enforceCallingPermission(android.Manifest.permission.WRITE_SETTINGS,
12440 "updateConfiguration()");
12441 if (values == null) {
12442 throw new NullPointerException("Configuration must not be null");
12443 }
12444
12445 synchronized(this) {
12446 final long origId = Binder.clearCallingIdentity();
12447 updateConfigurationLocked(values, null, true);
12448 Binder.restoreCallingIdentity(origId);
12449 }
12450 }
12451
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012452 public void updateConfiguration(Configuration values) {
12453 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
12454 "updateConfiguration()");
12455
12456 synchronized(this) {
12457 if (values == null && mWindowManager != null) {
12458 // sentinel: fetch the current configuration from the window manager
12459 values = mWindowManager.computeNewConfiguration();
12460 }
12461
12462 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn31ca8542011-07-19 14:58:28 -070012463 if (values != null) {
12464 Settings.System.clearConfiguration(values);
12465 }
12466 updateConfigurationLocked(values, null, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012467 Binder.restoreCallingIdentity(origId);
12468 }
12469 }
12470
12471 /**
12472 * Do either or both things: (1) change the current configuration, and (2)
12473 * make sure the given activity is running with the (now) current
12474 * configuration. Returns true if the activity has been left running, or
12475 * false if <var>starting</var> is being destroyed to match the new
12476 * configuration.
Dianne Hackborn31ca8542011-07-19 14:58:28 -070012477 * @param persistent TODO
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012478 */
12479 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn31ca8542011-07-19 14:58:28 -070012480 ActivityRecord starting, boolean persistent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012481 int changes = 0;
12482
12483 boolean kept = true;
12484
12485 if (values != null) {
12486 Configuration newConfig = new Configuration(mConfiguration);
12487 changes = newConfig.updateFrom(values);
12488 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070012489 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012490 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012491 }
12492
Doug Zongker2bec3d42009-12-04 12:52:44 -080012493 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012494
12495 if (values.locale != null) {
12496 saveLocaleLocked(values.locale,
12497 !values.locale.equals(mConfiguration.locale),
12498 values.userSetLocale);
12499 }
12500
Dianne Hackborne36d6e22010-02-17 19:46:25 -080012501 mConfigurationSeq++;
12502 if (mConfigurationSeq <= 0) {
12503 mConfigurationSeq = 1;
12504 }
12505 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012506 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012507 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080012508
12509 AttributeCache ac = AttributeCache.instance();
12510 if (ac != null) {
12511 ac.updateConfiguration(mConfiguration);
12512 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012513
Dianne Hackborn2f0b1752011-05-31 17:59:49 -070012514 // Make sure all resources in our process are updated
12515 // right now, so that anyone who is going to retrieve
12516 // resource values after we return will be sure to get
12517 // the new ones. This is especially important during
12518 // boot, where the first config change needs to guarantee
12519 // all resources have that config before following boot
12520 // code is executed.
12521 mSystemThread.applyConfigurationToResources(newConfig);
12522
Dianne Hackborn31ca8542011-07-19 14:58:28 -070012523 if (persistent && Settings.System.hasInterestingConfigurationChanges(changes)) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080012524 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
12525 msg.obj = new Configuration(mConfiguration);
12526 mHandler.sendMessage(msg);
12527 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012528
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012529 for (int i=mLruProcesses.size()-1; i>=0; i--) {
12530 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012531 try {
12532 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012533 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070012534 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012535 app.thread.scheduleConfigurationChanged(mConfiguration);
12536 }
12537 } catch (Exception e) {
12538 }
12539 }
12540 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012541 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
12542 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012543 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
12544 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080012545 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
12546 broadcastIntentLocked(null, null,
12547 new Intent(Intent.ACTION_LOCALE_CHANGED),
12548 null, null, 0, null, null,
12549 null, false, false, MY_PID, Process.SYSTEM_UID);
12550 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012551 }
12552 }
12553
12554 if (changes != 0 && starting == null) {
12555 // If the configuration changed, and the caller is not already
12556 // in the process of starting an activity, then find the top
12557 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012558 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012559 }
12560
12561 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012562 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
Dianne Hackborn5f4d6432010-12-21 20:40:11 -080012563 // And we need to make sure at this point that all other activities
12564 // are made visible with the correct configuration.
12565 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012566 }
12567
Dianne Hackborne36d6e22010-02-17 19:46:25 -080012568 if (values != null && mWindowManager != null) {
12569 mWindowManager.setNewConfiguration(mConfiguration);
12570 }
12571
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012572 return kept;
12573 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012574
12575 /**
12576 * Save the locale. You must be inside a synchronized (this) block.
12577 */
12578 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
12579 if(isDiff) {
12580 SystemProperties.set("user.language", l.getLanguage());
12581 SystemProperties.set("user.region", l.getCountry());
12582 }
12583
12584 if(isPersist) {
12585 SystemProperties.set("persist.sys.language", l.getLanguage());
12586 SystemProperties.set("persist.sys.country", l.getCountry());
12587 SystemProperties.set("persist.sys.localevar", l.getVariant());
12588 }
12589 }
12590
12591 // =========================================================
12592 // LIFETIME MANAGEMENT
12593 // =========================================================
12594
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012595 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
12596 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012597 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012598 // This adjustment has already been computed. If we are calling
12599 // from the top, we may have already computed our adjustment with
12600 // an earlier hidden adjustment that isn't really for us... if
12601 // so, use the new hidden adjustment.
12602 if (!recursed && app.hidden) {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070012603 app.curAdj = app.curRawAdj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012604 }
Dianne Hackbornc68c9132011-07-29 01:25:18 -070012605 return app.curRawAdj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012606 }
12607
12608 if (app.thread == null) {
12609 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012610 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012611 return (app.curAdj=EMPTY_APP_ADJ);
12612 }
12613
Dianne Hackbornc68c9132011-07-29 01:25:18 -070012614 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
12615 app.adjSource = null;
12616 app.adjTarget = null;
12617 app.empty = false;
12618 app.hidden = false;
12619
12620 final int activitiesSize = app.activities.size();
12621
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012622 if (app.maxAdj <= FOREGROUND_APP_ADJ) {
12623 // The max adjustment doesn't allow this app to be anything
12624 // below foreground, so it is not worth doing work for it.
12625 app.adjType = "fixed";
12626 app.adjSeq = mAdjSeq;
12627 app.curRawAdj = app.maxAdj;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070012628 app.foregroundActivities = false;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012629 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012630 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070012631 // System process can do UI, and when they do we want to have
12632 // them trim their memory after the user leaves the UI. To
12633 // facilitate this, here we need to determine whether or not it
12634 // is currently showing UI.
12635 app.systemNoUi = true;
12636 if (app == TOP_APP) {
12637 app.systemNoUi = false;
12638 } else if (activitiesSize > 0) {
12639 for (int j = 0; j < activitiesSize; j++) {
12640 final ActivityRecord r = app.activities.get(j);
12641 if (r.visible) {
12642 app.systemNoUi = false;
12643 break;
12644 }
12645 }
12646 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012647 return (app.curAdj=app.maxAdj);
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012648 }
12649
12650 final boolean hadForegroundActivities = app.foregroundActivities;
12651
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012652 app.foregroundActivities = false;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070012653 app.keeping = false;
12654 app.systemNoUi = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012655
The Android Open Source Project4df24232009-03-05 14:34:35 -080012656 // Determine the importance of the process, starting with most
12657 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012658 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012659 int schedGroup;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012660 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012661 // The last app on the list is the foreground app.
12662 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012663 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012664 app.adjType = "top-activity";
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012665 app.foregroundActivities = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012666 } else if (app.instrumentationClass != null) {
12667 // Don't want to kill running instrumentation.
12668 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012669 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012670 app.adjType = "instrumentation";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012671 } else if (app.curReceiver != null ||
12672 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
12673 // An app that is currently receiving a broadcast also
12674 // counts as being in the foreground.
12675 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012676 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012677 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012678 } else if (app.executingServices.size() > 0) {
12679 // An app that is currently executing a service callback also
12680 // counts as being in the foreground.
12681 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012682 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012683 app.adjType = "exec-service";
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012684 } else if (activitiesSize > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012685 // This app is in the background with paused activities.
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012686 // We inspect activities to potentially upgrade adjustment further below.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012687 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012688 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012689 app.hidden = true;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070012690 app.adjType = "bg-activities";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012691 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012692 // A very not-needed process. If this is lower in the lru list,
12693 // we will push it in to the empty bucket.
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012694 adj = hiddenAdj;
12695 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012696 app.hidden = true;
12697 app.empty = true;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012698 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012699 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012700
12701 // Examine all activities if not already foreground.
12702 if (!app.foregroundActivities && activitiesSize > 0) {
12703 for (int j = 0; j < activitiesSize; j++) {
12704 final ActivityRecord r = app.activities.get(j);
12705 if (r.visible) {
12706 // App has a visible activity; only upgrade adjustment.
12707 if (adj > VISIBLE_APP_ADJ) {
12708 adj = VISIBLE_APP_ADJ;
12709 app.adjType = "visible";
12710 }
12711 schedGroup = Process.THREAD_GROUP_DEFAULT;
12712 app.hidden = false;
12713 app.foregroundActivities = true;
12714 break;
12715 } else if (r.state == ActivityState.PAUSING || r.state == ActivityState.PAUSED
12716 || r.state == ActivityState.STOPPING) {
12717 // Only upgrade adjustment.
12718 if (adj > PERCEPTIBLE_APP_ADJ) {
12719 adj = PERCEPTIBLE_APP_ADJ;
12720 app.adjType = "stopping";
12721 }
12722 app.foregroundActivities = true;
12723 }
12724 }
12725 }
12726
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012727 if (adj > PERCEPTIBLE_APP_ADJ) {
12728 if (app.foregroundServices) {
12729 // The user is aware of this app, so make it visible.
12730 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012731 app.adjType = "foreground-service";
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012732 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012733 } else if (app.forcingToForeground != null) {
12734 // The user is aware of this app, so make it visible.
12735 adj = PERCEPTIBLE_APP_ADJ;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012736 app.adjType = "force-foreground";
12737 app.adjSource = app.forcingToForeground;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012738 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012739 }
12740 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012741
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012742 if (adj > HEAVY_WEIGHT_APP_ADJ && app == mHeavyWeightProcess) {
12743 // We don't want to kill the current heavy-weight process.
12744 adj = HEAVY_WEIGHT_APP_ADJ;
12745 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
12746 app.adjType = "heavy";
12747 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012748
Dianne Hackborn83a6f452011-01-27 17:17:19 -080012749 if (adj > HOME_APP_ADJ && app == mHomeProcess) {
12750 // This process is hosting what we currently consider to be the
12751 // home app, so we don't want to let it go into the background.
12752 adj = HOME_APP_ADJ;
12753 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
12754 app.adjType = "home";
12755 }
12756
Joe Onorato8a9b2202010-02-26 18:56:32 -080012757 //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj);
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012758
The Android Open Source Project4df24232009-03-05 14:34:35 -080012759 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012760 // there are applications dependent on our services or providers, but
12761 // this gives us a baseline and makes sure we don't get into an
12762 // infinite recursion.
12763 app.adjSeq = mAdjSeq;
12764 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012765
Christopher Tate6fa95972009-06-05 18:43:55 -070012766 if (mBackupTarget != null && app == mBackupTarget.app) {
12767 // If possible we want to avoid killing apps while they're being backed up
12768 if (adj > BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012769 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Christopher Tate6fa95972009-06-05 18:43:55 -070012770 adj = BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012771 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012772 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070012773 }
12774 }
12775
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012776 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
12777 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012778 final long now = SystemClock.uptimeMillis();
12779 // This process is more important if the top activity is
12780 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070012781 Iterator<ServiceRecord> jt = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012782 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012783 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012784 if (s.startRequested) {
Dianne Hackbornf0754f5b2011-07-21 16:02:07 -070012785 if (app.hasShownUi) {
12786 // If this process has shown some UI, let it immediately
12787 // go to the LRU list because it may be pretty heavy with
12788 // UI stuff. We'll tag it with a label just to help
12789 // debug and understand what is going on.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012790 if (adj > SECONDARY_SERVER_ADJ) {
Dianne Hackbornf0754f5b2011-07-21 16:02:07 -070012791 app.adjType = "started-bg-ui-services";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012792 }
Dianne Hackbornf0754f5b2011-07-21 16:02:07 -070012793 } else {
12794 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
12795 // This service has seen some activity within
12796 // recent memory, so we will keep its process ahead
12797 // of the background processes.
12798 if (adj > SECONDARY_SERVER_ADJ) {
12799 adj = SECONDARY_SERVER_ADJ;
12800 app.adjType = "started-services";
12801 app.hidden = false;
12802 }
12803 }
12804 // If we have let the service slide into the background
12805 // state, still have some text describing what it is doing
12806 // even though the service no longer has an impact.
12807 if (adj > SECONDARY_SERVER_ADJ) {
12808 app.adjType = "started-bg-services";
12809 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080012810 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012811 // Don't kill this process because it is doing work; it
12812 // has said it is doing work.
12813 app.keeping = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012814 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012815 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
12816 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012817 Iterator<ArrayList<ConnectionRecord>> kt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012818 = s.connections.values().iterator();
12819 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012820 ArrayList<ConnectionRecord> clist = kt.next();
12821 for (int i=0; i<clist.size() && adj > FOREGROUND_APP_ADJ; i++) {
12822 // XXX should compute this based on the max of
12823 // all connected clients.
12824 ConnectionRecord cr = clist.get(i);
12825 if (cr.binding.client == app) {
12826 // Binding to ourself is not interesting.
12827 continue;
12828 }
Dianne Hackbornc68c9132011-07-29 01:25:18 -070012829 if ((cr.flags&Context.BIND_WAIVE_PRIORITY) == 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012830 ProcessRecord client = cr.binding.client;
Dianne Hackborn130b0d22011-07-26 22:07:48 -070012831 int clientAdj = adj;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012832 int myHiddenAdj = hiddenAdj;
12833 if (myHiddenAdj > client.hiddenAdj) {
12834 if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
12835 myHiddenAdj = client.hiddenAdj;
12836 } else {
12837 myHiddenAdj = VISIBLE_APP_ADJ;
12838 }
12839 }
Dianne Hackborn130b0d22011-07-26 22:07:48 -070012840 clientAdj = computeOomAdjLocked(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012841 client, myHiddenAdj, TOP_APP, true);
Dianne Hackborn130b0d22011-07-26 22:07:48 -070012842 String adjType = null;
12843 if ((cr.flags&Context.BIND_ALLOW_OOM_MANAGEMENT) != 0) {
12844 // Not doing bind OOM management, so treat
12845 // this guy more like a started service.
12846 if (app.hasShownUi) {
12847 // If this process has shown some UI, let it immediately
12848 // go to the LRU list because it may be pretty heavy with
12849 // UI stuff. We'll tag it with a label just to help
12850 // debug and understand what is going on.
12851 if (adj > clientAdj) {
12852 adjType = "bound-bg-ui-services";
12853 }
12854 clientAdj = adj;
12855 } else {
12856 if (now >= (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
12857 // This service has not seen activity within
12858 // recent memory, so allow it to drop to the
12859 // LRU list if there is no other reason to keep
12860 // it around. We'll also tag it with a label just
12861 // to help debug and undertand what is going on.
12862 if (adj > clientAdj) {
12863 adjType = "bound-bg-services";
12864 }
12865 clientAdj = adj;
12866 }
12867 }
12868 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012869 if (adj > clientAdj) {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070012870 // If this process has recently shown UI, and
12871 // the process that is binding to it is less
12872 // important than being visible, then we don't
12873 // care about the binding as much as we care
12874 // about letting this process get into the LRU
12875 // list to be killed and restarted if needed for
12876 // memory.
12877 if (app.hasShownUi && clientAdj > PERCEPTIBLE_APP_ADJ) {
12878 adjType = "bound-bg-ui-services";
12879 } else {
12880 if ((cr.flags&(Context.BIND_ABOVE_CLIENT
12881 |Context.BIND_IMPORTANT)) != 0) {
12882 adj = clientAdj;
12883 } else if (clientAdj >= VISIBLE_APP_ADJ) {
12884 adj = clientAdj;
12885 } else {
12886 adj = VISIBLE_APP_ADJ;
12887 }
12888 if (!client.hidden) {
12889 app.hidden = false;
12890 }
12891 if (client.keeping) {
12892 app.keeping = true;
12893 }
12894 adjType = "service";
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012895 }
Dianne Hackborn130b0d22011-07-26 22:07:48 -070012896 }
12897 if (adjType != null) {
12898 app.adjType = adjType;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070012899 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12900 .REASON_SERVICE_IN_USE;
12901 app.adjSource = cr.binding.client;
12902 app.adjTarget = s.name;
12903 }
12904 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
12905 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
12906 schedGroup = Process.THREAD_GROUP_DEFAULT;
12907 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012908 }
12909 }
Dianne Hackbornc68c9132011-07-29 01:25:18 -070012910 if ((cr.flags&Context.BIND_ADJUST_WITH_ACTIVITY) != 0) {
12911 ActivityRecord a = cr.activity;
12912 if (a != null && adj > FOREGROUND_APP_ADJ &&
12913 (a.visible || a.state == ActivityState.RESUMED
12914 || a.state == ActivityState.PAUSING)) {
12915 adj = FOREGROUND_APP_ADJ;
12916 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
12917 schedGroup = Process.THREAD_GROUP_DEFAULT;
12918 }
12919 app.hidden = false;
12920 app.adjType = "service";
12921 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12922 .REASON_SERVICE_IN_USE;
12923 app.adjSource = a;
12924 app.adjTarget = s.name;
12925 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012926 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012927 }
12928 }
12929 }
12930 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012931
Dianne Hackborn287952c2010-09-22 22:34:31 -070012932 // Finally, if this process has active services running in it, we
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012933 // would like to avoid killing it unless it would prevent the current
12934 // application from running. By default we put the process in
12935 // with the rest of the background processes; as we scan through
12936 // its services we may bump it up from there.
12937 if (adj > hiddenAdj) {
12938 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012939 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070012940 app.adjType = "bg-services";
12941 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012942 }
12943
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012944 if (app.pubProviders.size() != 0 && (adj > FOREGROUND_APP_ADJ
12945 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012946 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012947 while (jt.hasNext() && (adj > FOREGROUND_APP_ADJ
12948 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070012949 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012950 if (cpr.clients.size() != 0) {
12951 Iterator<ProcessRecord> kt = cpr.clients.iterator();
12952 while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
12953 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070012954 if (client == app) {
12955 // Being our own client is not interesting.
12956 continue;
12957 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012958 int myHiddenAdj = hiddenAdj;
12959 if (myHiddenAdj > client.hiddenAdj) {
12960 if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
12961 myHiddenAdj = client.hiddenAdj;
12962 } else {
12963 myHiddenAdj = FOREGROUND_APP_ADJ;
12964 }
12965 }
12966 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012967 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012968 if (adj > clientAdj) {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070012969 if (app.hasShownUi && clientAdj > PERCEPTIBLE_APP_ADJ) {
12970 app.adjType = "bg-ui-provider";
12971 } else {
12972 adj = clientAdj > FOREGROUND_APP_ADJ
12973 ? clientAdj : FOREGROUND_APP_ADJ;
12974 app.adjType = "provider";
12975 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012976 if (!client.hidden) {
12977 app.hidden = false;
12978 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070012979 if (client.keeping) {
12980 app.keeping = true;
12981 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070012982 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
12983 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012984 app.adjSource = client;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070012985 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012986 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012987 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
12988 schedGroup = Process.THREAD_GROUP_DEFAULT;
12989 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012990 }
12991 }
12992 // If the provider has external (non-framework) process
12993 // dependencies, ensure that its adjustment is at least
12994 // FOREGROUND_APP_ADJ.
12995 if (cpr.externals != 0) {
12996 if (adj > FOREGROUND_APP_ADJ) {
12997 adj = FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012998 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012999 app.hidden = false;
Dianne Hackborn287952c2010-09-22 22:34:31 -070013000 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013001 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070013002 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013003 }
13004 }
13005 }
13006 }
13007
13008 app.curRawAdj = adj;
13009
Joe Onorato8a9b2202010-02-26 18:56:32 -080013010 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013011 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
13012 if (adj > app.maxAdj) {
13013 adj = app.maxAdj;
Dianne Hackborn32907cf2010-06-10 17:50:20 -070013014 if (app.maxAdj <= PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013015 schedGroup = Process.THREAD_GROUP_DEFAULT;
13016 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013017 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070013018 if (adj < HIDDEN_APP_MIN_ADJ) {
13019 app.keeping = true;
13020 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013021
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013022 if (app.hasAboveClient) {
13023 // If this process has bound to any services with BIND_ABOVE_CLIENT,
13024 // then we need to drop its adjustment to be lower than the service's
13025 // in order to honor the request. We want to drop it by one adjustment
13026 // level... but there is special meaning applied to various levels so
13027 // we will skip some of them.
13028 if (adj < FOREGROUND_APP_ADJ) {
13029 // System process will not get dropped, ever
13030 } else if (adj < VISIBLE_APP_ADJ) {
13031 adj = VISIBLE_APP_ADJ;
13032 } else if (adj < PERCEPTIBLE_APP_ADJ) {
13033 adj = PERCEPTIBLE_APP_ADJ;
13034 } else if (adj < HIDDEN_APP_MIN_ADJ) {
13035 adj = HIDDEN_APP_MIN_ADJ;
13036 } else if (adj < EMPTY_APP_ADJ) {
13037 adj++;
13038 }
13039 }
13040
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013041 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013042 app.curSchedGroup = schedGroup;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013043
13044 if (hadForegroundActivities != app.foregroundActivities) {
Jeff Sharkey287bd832011-05-28 19:36:26 -070013045 mHandler.obtainMessage(DISPATCH_FOREGROUND_ACTIVITIES_CHANGED, app.pid, app.info.uid,
13046 app.foregroundActivities).sendToTarget();
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013047 }
13048
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013049 return app.curRawAdj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013050 }
13051
13052 /**
13053 * Ask a given process to GC right now.
13054 */
13055 final void performAppGcLocked(ProcessRecord app) {
13056 try {
13057 app.lastRequestedGc = SystemClock.uptimeMillis();
13058 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013059 if (app.reportLowMemory) {
13060 app.reportLowMemory = false;
13061 app.thread.scheduleLowMemory();
13062 } else {
13063 app.thread.processInBackground();
13064 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013065 }
13066 } catch (Exception e) {
13067 // whatever.
13068 }
13069 }
13070
13071 /**
13072 * Returns true if things are idle enough to perform GCs.
13073 */
Josh Bartel7f208742010-02-25 11:01:44 -060013074 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013075 return mParallelBroadcasts.size() == 0
13076 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013077 && (mSleeping || (mMainStack.mResumedActivity != null &&
13078 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013079 }
13080
13081 /**
13082 * Perform GCs on all processes that are waiting for it, but only
13083 * if things are idle.
13084 */
13085 final void performAppGcsLocked() {
13086 final int N = mProcessesToGc.size();
13087 if (N <= 0) {
13088 return;
13089 }
Josh Bartel7f208742010-02-25 11:01:44 -060013090 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013091 while (mProcessesToGc.size() > 0) {
13092 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn32907cf2010-06-10 17:50:20 -070013093 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013094 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
13095 <= SystemClock.uptimeMillis()) {
13096 // To avoid spamming the system, we will GC processes one
13097 // at a time, waiting a few seconds between each.
13098 performAppGcLocked(proc);
13099 scheduleAppGcsLocked();
13100 return;
13101 } else {
13102 // It hasn't been long enough since we last GCed this
13103 // process... put it in the list to wait for its time.
13104 addProcessToGcListLocked(proc);
13105 break;
13106 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013107 }
13108 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013109
13110 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013111 }
13112 }
13113
13114 /**
13115 * If all looks good, perform GCs on all processes waiting for them.
13116 */
13117 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060013118 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013119 performAppGcsLocked();
13120 return;
13121 }
13122 // Still not idle, wait some more.
13123 scheduleAppGcsLocked();
13124 }
13125
13126 /**
13127 * Schedule the execution of all pending app GCs.
13128 */
13129 final void scheduleAppGcsLocked() {
13130 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013131
13132 if (mProcessesToGc.size() > 0) {
13133 // Schedule a GC for the time to the next process.
13134 ProcessRecord proc = mProcessesToGc.get(0);
13135 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
13136
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013137 long when = proc.lastRequestedGc + GC_MIN_INTERVAL;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013138 long now = SystemClock.uptimeMillis();
13139 if (when < (now+GC_TIMEOUT)) {
13140 when = now + GC_TIMEOUT;
13141 }
13142 mHandler.sendMessageAtTime(msg, when);
13143 }
13144 }
13145
13146 /**
13147 * Add a process to the array of processes waiting to be GCed. Keeps the
13148 * list in sorted order by the last GC time. The process can't already be
13149 * on the list.
13150 */
13151 final void addProcessToGcListLocked(ProcessRecord proc) {
13152 boolean added = false;
13153 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
13154 if (mProcessesToGc.get(i).lastRequestedGc <
13155 proc.lastRequestedGc) {
13156 added = true;
13157 mProcessesToGc.add(i+1, proc);
13158 break;
13159 }
13160 }
13161 if (!added) {
13162 mProcessesToGc.add(0, proc);
13163 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013164 }
13165
13166 /**
13167 * Set up to ask a process to GC itself. This will either do it
13168 * immediately, or put it on the list of processes to gc the next
13169 * time things are idle.
13170 */
13171 final void scheduleAppGcLocked(ProcessRecord app) {
13172 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013173 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013174 return;
13175 }
13176 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013177 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013178 scheduleAppGcsLocked();
13179 }
13180 }
13181
Dianne Hackborn287952c2010-09-22 22:34:31 -070013182 final void checkExcessivePowerUsageLocked(boolean doKills) {
13183 updateCpuStatsNow();
13184
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013185 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
Dianne Hackborn287952c2010-09-22 22:34:31 -070013186 boolean doWakeKills = doKills;
13187 boolean doCpuKills = doKills;
13188 if (mLastPowerCheckRealtime == 0) {
13189 doWakeKills = false;
13190 }
13191 if (mLastPowerCheckUptime == 0) {
13192 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013193 }
13194 if (stats.isScreenOn()) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070013195 doWakeKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013196 }
13197 final long curRealtime = SystemClock.elapsedRealtime();
Dianne Hackborn287952c2010-09-22 22:34:31 -070013198 final long realtimeSince = curRealtime - mLastPowerCheckRealtime;
13199 final long curUptime = SystemClock.uptimeMillis();
13200 final long uptimeSince = curUptime - mLastPowerCheckUptime;
13201 mLastPowerCheckRealtime = curRealtime;
13202 mLastPowerCheckUptime = curUptime;
13203 if (realtimeSince < WAKE_LOCK_MIN_CHECK_DURATION) {
13204 doWakeKills = false;
13205 }
13206 if (uptimeSince < CPU_MIN_CHECK_DURATION) {
13207 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013208 }
13209 int i = mLruProcesses.size();
13210 while (i > 0) {
13211 i--;
13212 ProcessRecord app = mLruProcesses.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -070013213 if (!app.keeping) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013214 long wtime;
13215 synchronized (stats) {
13216 wtime = stats.getProcessWakeTime(app.info.uid,
13217 app.pid, curRealtime);
13218 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070013219 long wtimeUsed = wtime - app.lastWakeTime;
13220 long cputimeUsed = app.curCpuTime - app.lastCpuTime;
13221 if (DEBUG_POWER) {
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070013222 StringBuilder sb = new StringBuilder(128);
13223 sb.append("Wake for ");
13224 app.toShortString(sb);
13225 sb.append(": over ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070013226 TimeUtils.formatDuration(realtimeSince, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070013227 sb.append(" used ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070013228 TimeUtils.formatDuration(wtimeUsed, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070013229 sb.append(" (");
Dianne Hackborn287952c2010-09-22 22:34:31 -070013230 sb.append((wtimeUsed*100)/realtimeSince);
13231 sb.append("%)");
13232 Slog.i(TAG, sb.toString());
13233 sb.setLength(0);
13234 sb.append("CPU for ");
13235 app.toShortString(sb);
13236 sb.append(": over ");
13237 TimeUtils.formatDuration(uptimeSince, sb);
13238 sb.append(" used ");
13239 TimeUtils.formatDuration(cputimeUsed, sb);
13240 sb.append(" (");
13241 sb.append((cputimeUsed*100)/uptimeSince);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070013242 sb.append("%)");
13243 Slog.i(TAG, sb.toString());
13244 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013245 // If a process has held a wake lock for more
13246 // than 50% of the time during this period,
13247 // that sounds pad. Kill!
Dianne Hackborn287952c2010-09-22 22:34:31 -070013248 if (doWakeKills && realtimeSince > 0
13249 && ((wtimeUsed*100)/realtimeSince) >= 50) {
13250 synchronized (stats) {
13251 stats.reportExcessiveWakeLocked(app.info.uid, app.processName,
13252 realtimeSince, wtimeUsed);
13253 }
13254 Slog.w(TAG, "Excessive wake lock in " + app.processName
13255 + " (pid " + app.pid + "): held " + wtimeUsed
13256 + " during " + realtimeSince);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013257 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13258 app.processName, app.setAdj, "excessive wake lock");
13259 Process.killProcessQuiet(app.pid);
Dianne Hackborn287952c2010-09-22 22:34:31 -070013260 } else if (doCpuKills && uptimeSince > 0
13261 && ((cputimeUsed*100)/uptimeSince) >= 50) {
13262 synchronized (stats) {
13263 stats.reportExcessiveCpuLocked(app.info.uid, app.processName,
13264 uptimeSince, cputimeUsed);
13265 }
13266 Slog.w(TAG, "Excessive CPU in " + app.processName
13267 + " (pid " + app.pid + "): used " + cputimeUsed
13268 + " during " + uptimeSince);
13269 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13270 app.processName, app.setAdj, "excessive cpu");
13271 Process.killProcessQuiet(app.pid);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013272 } else {
13273 app.lastWakeTime = wtime;
Dianne Hackborn287952c2010-09-22 22:34:31 -070013274 app.lastCpuTime = app.curCpuTime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013275 }
13276 }
13277 }
13278 }
13279
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013280 private final void updateOomAdjLocked(
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013281 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013282 app.hiddenAdj = hiddenAdj;
13283
13284 if (app.thread == null) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013285 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013286 }
13287
Dianne Hackborn287952c2010-09-22 22:34:31 -070013288 final boolean wasKeeping = app.keeping;
13289
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013290 computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013291
Jeff Brown10e89712011-07-08 18:52:57 -070013292 if (app.curRawAdj != app.setRawAdj) {
13293 if (app.curRawAdj > FOREGROUND_APP_ADJ
13294 && app.setRawAdj <= FOREGROUND_APP_ADJ) {
13295 // If this app is transitioning from foreground to
13296 // non-foreground, have it do a gc.
13297 scheduleAppGcLocked(app);
13298 } else if (app.curRawAdj >= HIDDEN_APP_MIN_ADJ
13299 && app.setRawAdj < HIDDEN_APP_MIN_ADJ) {
13300 // Likewise do a gc when an app is moving in to the
13301 // background (such as a service stopping).
13302 scheduleAppGcLocked(app);
13303 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070013304
Jeff Brown10e89712011-07-08 18:52:57 -070013305 if (wasKeeping && !app.keeping) {
13306 // This app is no longer something we want to keep. Note
13307 // its current wake lock time to later know to kill it if
13308 // it is not behaving well.
13309 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
13310 synchronized (stats) {
13311 app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
13312 app.pid, SystemClock.elapsedRealtime());
13313 }
13314 app.lastCpuTime = app.curCpuTime;
13315 }
13316
13317 app.setRawAdj = app.curRawAdj;
13318 }
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013319 if (app.curAdj != app.setAdj) {
13320 if (Process.setOomAdj(app.pid, app.curAdj)) {
Jeff Brown10e89712011-07-08 18:52:57 -070013321 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
13322 TAG, "Set app " + app.processName +
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013323 " oom adj to " + app.curAdj + " because " + app.adjType);
13324 app.setAdj = app.curAdj;
Jeff Brown10e89712011-07-08 18:52:57 -070013325 } else {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013326 Slog.w(TAG, "Failed setting oom adj of " + app + " to " + app.curAdj);
Jeff Brown10e89712011-07-08 18:52:57 -070013327 }
13328 }
13329 if (app.setSchedGroup != app.curSchedGroup) {
13330 app.setSchedGroup = app.curSchedGroup;
13331 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
13332 "Setting process group of " + app.processName
13333 + " to " + app.curSchedGroup);
13334 if (app.waitingToKill != null &&
13335 app.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {
13336 Slog.i(TAG, "Killing " + app.toShortString() + ": " + app.waitingToKill);
13337 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13338 app.processName, app.setAdj, app.waitingToKill);
13339 Process.killProcessQuiet(app.pid);
13340 } else {
13341 if (true) {
13342 long oldId = Binder.clearCallingIdentity();
13343 try {
13344 Process.setProcessGroup(app.pid, app.curSchedGroup);
13345 } catch (Exception e) {
13346 Slog.w(TAG, "Failed setting process group of " + app.pid
13347 + " to " + app.curSchedGroup);
13348 e.printStackTrace();
13349 } finally {
13350 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013351 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013352 } else {
Jeff Brown10e89712011-07-08 18:52:57 -070013353 if (app.thread != null) {
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013354 try {
Jeff Brown10e89712011-07-08 18:52:57 -070013355 app.thread.setSchedulingGroup(app.curSchedGroup);
13356 } catch (RemoteException e) {
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013357 }
13358 }
13359 }
13360 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013361 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013362 }
13363
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013364 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013365 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013366 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013367 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013368 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013369 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013370 }
13371 }
13372 return resumedActivity;
13373 }
13374
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013375 private final void updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013376 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013377 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
13378 int curAdj = app.curAdj;
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013379 final boolean wasHidden = curAdj >= HIDDEN_APP_MIN_ADJ
13380 && curAdj <= HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013381
13382 mAdjSeq++;
13383
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013384 updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
13385 final boolean nowHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
13386 && app.curAdj <= HIDDEN_APP_MAX_ADJ;
13387 if (nowHidden != wasHidden) {
13388 // Changed to/from hidden state, so apps after it in the LRU
13389 // list may also be changed.
13390 updateOomAdjLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013391 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013392 }
13393
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013394 final void updateOomAdjLocked() {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013395 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013396 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
13397
13398 if (false) {
13399 RuntimeException e = new RuntimeException();
13400 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080013401 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013402 }
13403
13404 mAdjSeq++;
13405
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013406 // Let's determine how many processes we have running vs.
13407 // how many slots we have for background processes; we may want
13408 // to put multiple processes in a slot of there are enough of
13409 // them.
13410 int numSlots = HIDDEN_APP_MAX_ADJ - HIDDEN_APP_MIN_ADJ + 1;
13411 int factor = (mLruProcesses.size()-4)/numSlots;
13412 if (factor < 1) factor = 1;
13413 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070013414 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013415
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013416 // First update the OOM adjustment for each of the
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013417 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013418 int i = mLruProcesses.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013419 int curHiddenAdj = HIDDEN_APP_MIN_ADJ;
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013420 int numBg = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013421 while (i > 0) {
13422 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013423 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013424 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013425 updateOomAdjLocked(app, curHiddenAdj, TOP_APP);
13426 if (curHiddenAdj < EMPTY_APP_ADJ
13427 && app.curAdj == curHiddenAdj) {
13428 step++;
13429 if (step >= factor) {
13430 step = 0;
13431 curHiddenAdj++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013432 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013433 }
13434 if (!app.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -070013435 if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013436 numHidden++;
13437 if (numHidden > mProcessLimit) {
13438 Slog.i(TAG, "No longer want " + app.processName
13439 + " (pid " + app.pid + "): hidden #" + numHidden);
13440 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13441 app.processName, app.setAdj, "too many background");
13442 app.killedBackground = true;
13443 Process.killProcessQuiet(app.pid);
13444 } else {
13445 numBg++;
Dianne Hackborn8633e682010-04-22 16:03:41 -070013446 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013447 } else if (app.curAdj >= HOME_APP_ADJ) {
13448 numBg++;
Dianne Hackborn8633e682010-04-22 16:03:41 -070013449 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013450 }
13451 }
13452
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013453 // Now determine the memory trimming level of background processes.
13454 // Unfortunately we need to start at the back of the list to do this
13455 // properly. We only do this if the number of background apps we
13456 // are managing to keep around is less than half the maximum we desire;
13457 // if we are keeping a good number around, we'll let them use whatever
13458 // memory they want.
13459 if (numHidden <= (MAX_HIDDEN_APPS/2)) {
13460 final int N = mLruProcesses.size();
13461 factor = numBg/3;
13462 step = 0;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013463 int curLevel = ComponentCallbacks2.TRIM_MEMORY_COMPLETE;
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013464 for (i=0; i<N; i++) {
13465 ProcessRecord app = mLruProcesses.get(i);
13466 if (app.curAdj >= HIDDEN_APP_MIN_ADJ && !app.killedBackground) {
13467 if (app.trimMemoryLevel < curLevel && app.thread != null) {
13468 try {
13469 app.thread.scheduleTrimMemory(curLevel);
13470 } catch (RemoteException e) {
13471 }
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013472 if (curLevel >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013473 // For these apps we will also finish their activities
13474 // to help them free memory.
13475 mMainStack.destroyActivitiesLocked(app, false);
13476 }
13477 }
13478 app.trimMemoryLevel = curLevel;
13479 step++;
13480 if (step >= factor) {
13481 switch (curLevel) {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013482 case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:
13483 curLevel = ComponentCallbacks2.TRIM_MEMORY_MODERATE;
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013484 break;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013485 case ComponentCallbacks2.TRIM_MEMORY_MODERATE:
13486 curLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013487 break;
13488 }
13489 }
Dianne Hackbornf0754f5b2011-07-21 16:02:07 -070013490 } else if (app.curAdj == HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013491 if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_BACKGROUND
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013492 && app.thread != null) {
13493 try {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013494 app.thread.scheduleTrimMemory(
13495 ComponentCallbacks2.TRIM_MEMORY_BACKGROUND);
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013496 } catch (RemoteException e) {
13497 }
13498 }
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013499 app.trimMemoryLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
13500 } else if ((app.curAdj > VISIBLE_APP_ADJ || app.systemNoUi)
13501 && app.pendingUiClean) {
13502 if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN
13503 && app.thread != null) {
13504 try {
13505 app.thread.scheduleTrimMemory(
13506 ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
13507 } catch (RemoteException e) {
13508 }
13509 }
13510 app.trimMemoryLevel = ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN;
13511 app.pendingUiClean = false;
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013512 } else {
13513 app.trimMemoryLevel = 0;
13514 }
13515 }
13516 } else {
13517 final int N = mLruProcesses.size();
13518 for (i=0; i<N; i++) {
13519 ProcessRecord app = mLruProcesses.get(i);
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013520 if ((app.curAdj > VISIBLE_APP_ADJ || app.systemNoUi)
13521 && app.pendingUiClean) {
13522 if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN
13523 && app.thread != null) {
13524 try {
13525 app.thread.scheduleTrimMemory(
13526 ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
13527 } catch (RemoteException e) {
13528 }
13529 }
13530 app.trimMemoryLevel = ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN;
13531 app.pendingUiClean = false;
13532 } else {
13533 app.trimMemoryLevel = 0;
13534 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013535 }
13536 }
13537
13538 if (mAlwaysFinishActivities) {
13539 mMainStack.destroyActivitiesLocked(null, false);
13540 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013541 }
13542
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013543 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013544 synchronized (this) {
13545 int i;
13546
13547 // First remove any unused application processes whose package
13548 // has been removed.
13549 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
13550 final ProcessRecord app = mRemovedProcesses.get(i);
13551 if (app.activities.size() == 0
13552 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013553 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013554 TAG, "Exiting empty application process "
13555 + app.processName + " ("
13556 + (app.thread != null ? app.thread.asBinder() : null)
13557 + ")\n");
13558 if (app.pid > 0 && app.pid != MY_PID) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070013559 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13560 app.processName, app.setAdj, "empty");
13561 Process.killProcessQuiet(app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013562 } else {
13563 try {
13564 app.thread.scheduleExit();
13565 } catch (Exception e) {
13566 // Ignore exceptions.
13567 }
13568 }
Dianne Hackborn130b0d22011-07-26 22:07:48 -070013569 cleanUpApplicationRecordLocked(app, false, true, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013570 mRemovedProcesses.remove(i);
13571
13572 if (app.persistent) {
13573 if (app.persistent) {
13574 addAppLocked(app.info);
13575 }
13576 }
13577 }
13578 }
13579
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013580 // Now update the oom adj for all processes.
13581 updateOomAdjLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013582 }
13583 }
13584
13585 /** This method sends the specified signal to each of the persistent apps */
13586 public void signalPersistentProcesses(int sig) throws RemoteException {
13587 if (sig != Process.SIGNAL_USR1) {
13588 throw new SecurityException("Only SIGNAL_USR1 is allowed");
13589 }
13590
13591 synchronized (this) {
13592 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
13593 != PackageManager.PERMISSION_GRANTED) {
13594 throw new SecurityException("Requires permission "
13595 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
13596 }
13597
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013598 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
13599 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013600 if (r.thread != null && r.persistent) {
13601 Process.sendSignal(r.pid, sig);
13602 }
13603 }
13604 }
13605 }
13606
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013607 public boolean profileControl(String process, boolean start,
Romain Guy7eabe552011-07-21 14:56:34 -070013608 String path, ParcelFileDescriptor fd, int profileType) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013609
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013610 try {
13611 synchronized (this) {
13612 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
13613 // its own permission.
13614 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
13615 != PackageManager.PERMISSION_GRANTED) {
13616 throw new SecurityException("Requires permission "
13617 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013618 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013619
13620 if (start && fd == null) {
13621 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013622 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013623
13624 ProcessRecord proc = null;
13625 try {
13626 int pid = Integer.parseInt(process);
13627 synchronized (mPidsSelfLocked) {
13628 proc = mPidsSelfLocked.get(pid);
13629 }
13630 } catch (NumberFormatException e) {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013631 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013632
13633 if (proc == null) {
13634 HashMap<String, SparseArray<ProcessRecord>> all
13635 = mProcessNames.getMap();
13636 SparseArray<ProcessRecord> procs = all.get(process);
13637 if (procs != null && procs.size() > 0) {
13638 proc = procs.valueAt(0);
13639 }
13640 }
13641
13642 if (proc == null || proc.thread == null) {
13643 throw new IllegalArgumentException("Unknown process: " + process);
13644 }
13645
Dianne Hackbornf02e57b2011-03-01 22:21:04 -080013646 boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
13647 if (!isDebuggable) {
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013648 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
13649 throw new SecurityException("Process not debuggable: " + proc);
13650 }
13651 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013652
Romain Guy7eabe552011-07-21 14:56:34 -070013653 proc.thread.profilerControl(start, path, fd, profileType);
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013654 fd = null;
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013655 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070013656 }
13657 } catch (RemoteException e) {
13658 throw new IllegalStateException("Process disappeared");
13659 } finally {
13660 if (fd != null) {
13661 try {
13662 fd.close();
13663 } catch (IOException e) {
13664 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013665 }
13666 }
13667 }
Andy McFadden824c5102010-07-09 16:26:57 -070013668
13669 public boolean dumpHeap(String process, boolean managed,
13670 String path, ParcelFileDescriptor fd) throws RemoteException {
13671
13672 try {
13673 synchronized (this) {
13674 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
13675 // its own permission (same as profileControl).
13676 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
13677 != PackageManager.PERMISSION_GRANTED) {
13678 throw new SecurityException("Requires permission "
13679 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
13680 }
13681
13682 if (fd == null) {
13683 throw new IllegalArgumentException("null fd");
13684 }
13685
13686 ProcessRecord proc = null;
13687 try {
13688 int pid = Integer.parseInt(process);
13689 synchronized (mPidsSelfLocked) {
13690 proc = mPidsSelfLocked.get(pid);
13691 }
13692 } catch (NumberFormatException e) {
13693 }
13694
13695 if (proc == null) {
13696 HashMap<String, SparseArray<ProcessRecord>> all
13697 = mProcessNames.getMap();
13698 SparseArray<ProcessRecord> procs = all.get(process);
13699 if (procs != null && procs.size() > 0) {
13700 proc = procs.valueAt(0);
13701 }
13702 }
13703
13704 if (proc == null || proc.thread == null) {
13705 throw new IllegalArgumentException("Unknown process: " + process);
13706 }
13707
Dianne Hackbornf02e57b2011-03-01 22:21:04 -080013708 boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
13709 if (!isDebuggable) {
Andy McFadden824c5102010-07-09 16:26:57 -070013710 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
13711 throw new SecurityException("Process not debuggable: " + proc);
13712 }
13713 }
13714
13715 proc.thread.dumpHeap(managed, path, fd);
13716 fd = null;
13717 return true;
13718 }
13719 } catch (RemoteException e) {
13720 throw new IllegalStateException("Process disappeared");
13721 } finally {
13722 if (fd != null) {
13723 try {
13724 fd.close();
13725 } catch (IOException e) {
13726 }
13727 }
13728 }
13729 }
13730
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013731 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
13732 public void monitor() {
13733 synchronized (this) { }
13734 }
Svetoslav Ganov54d068e2011-03-02 12:58:40 -080013735
13736 public void onCoreSettingsChange(Bundle settings) {
13737 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
13738 ProcessRecord processRecord = mLruProcesses.get(i);
13739 try {
13740 if (processRecord.thread != null) {
13741 processRecord.thread.setCoreSettings(settings);
13742 }
13743 } catch (RemoteException re) {
13744 /* ignore */
13745 }
13746 }
13747 }
Amith Yamasani4b2e9342011-03-31 12:38:53 -070013748
13749 // Multi-user methods
13750
13751 public boolean switchUser(int userid) {
13752 // TODO
13753 return true;
13754 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013755}