blob: 76845666291003013c29327916cd82a82105d399 [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;
Christopher Tate9ce685b2012-03-15 16:27:14 -0700107import android.os.UpdateLock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800108import android.provider.Settings;
Dianne Hackborn2a29b3a2012-03-15 15:48:38 -0700109import android.text.format.Time;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800110import android.util.EventLog;
Dianne Hackborn905577f2011-09-07 18:31:28 -0700111import android.util.Pair;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800112import android.util.Slog;
Joe Onorato5d3bea62010-03-01 13:44:29 -0800113import android.util.Log;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800114import android.util.PrintWriterPrinter;
115import android.util.SparseArray;
Dianne Hackborn1ebccf52010-08-15 13:04:34 -0700116import android.util.TimeUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800117import android.view.Gravity;
118import android.view.LayoutInflater;
119import android.view.View;
120import android.view.WindowManager;
121import android.view.WindowManagerPolicy;
122
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700123import java.io.BufferedInputStream;
124import java.io.BufferedOutputStream;
Dianne Hackborn04d6db32011-11-04 20:07:24 -0700125import java.io.BufferedReader;
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700126import java.io.DataInputStream;
127import java.io.DataOutputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800128import java.io.File;
129import java.io.FileDescriptor;
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700130import java.io.FileInputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800131import java.io.FileNotFoundException;
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700132import java.io.FileOutputStream;
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200133import java.io.IOException;
Dan Egnora455d192010-03-12 08:52:28 -0800134import java.io.InputStreamReader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800135import java.io.PrintWriter;
Dianne Hackborn04d6db32011-11-04 20:07:24 -0700136import java.io.StringWriter;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800137import java.lang.IllegalStateException;
138import java.lang.ref.WeakReference;
139import java.util.ArrayList;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700140import java.util.Collections;
141import java.util.Comparator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800142import java.util.HashMap;
143import java.util.HashSet;
144import java.util.Iterator;
145import java.util.List;
146import java.util.Locale;
147import java.util.Map;
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -0700148import java.util.Set;
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700149import java.util.concurrent.atomic.AtomicBoolean;
150import java.util.concurrent.atomic.AtomicLong;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800151
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700152public final class ActivityManagerService extends ActivityManagerNative
153 implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800154 static final String TAG = "ActivityManager";
155 static final boolean DEBUG = false;
Dianne Hackborne2515ee2011-04-27 18:52:56 -0400156 static final boolean localLOGV = DEBUG;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800157 static final boolean DEBUG_SWITCH = localLOGV || false;
158 static final boolean DEBUG_TASKS = localLOGV || false;
159 static final boolean DEBUG_PAUSE = localLOGV || false;
160 static final boolean DEBUG_OOM_ADJ = localLOGV || false;
161 static final boolean DEBUG_TRANSITION = localLOGV || false;
162 static final boolean DEBUG_BROADCAST = localLOGV || false;
Dianne Hackborn82f3f002009-06-16 18:49:05 -0700163 static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800164 static final boolean DEBUG_SERVICE = localLOGV || false;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700165 static final boolean DEBUG_SERVICE_EXECUTING = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800166 static final boolean DEBUG_VISBILITY = localLOGV || false;
167 static final boolean DEBUG_PROCESSES = localLOGV || false;
Dianne Hackborna1e989b2009-09-01 19:54:29 -0700168 static final boolean DEBUG_PROVIDER = localLOGV || false;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800169 static final boolean DEBUG_URI_PERMISSION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800170 static final boolean DEBUG_USER_LEAVING = localLOGV || false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700171 static final boolean DEBUG_RESULTS = localLOGV || false;
Dianne Hackborn98cfebc2011-10-18 13:17:33 -0700172 static final boolean DEBUG_BACKUP = localLOGV || false;
Dianne Hackborndc6b6352009-09-30 14:20:09 -0700173 static final boolean DEBUG_CONFIGURATION = localLOGV || false;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700174 static final boolean DEBUG_POWER = localLOGV || false;
175 static final boolean DEBUG_POWER_QUICK = DEBUG_POWER || false;
Christopher Tate9ce685b2012-03-15 16:27:14 -0700176 static final boolean DEBUG_IMMERSIVE = localLOGV || true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800177 static final boolean VALIDATE_TOKENS = false;
178 static final boolean SHOW_ACTIVITY_START_TIME = true;
179
180 // Control over CPU and battery monitoring.
181 static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes.
182 static final boolean MONITOR_CPU_USAGE = true;
183 static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds.
184 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample.
185 static final boolean MONITOR_THREAD_CPU_USAGE = false;
186
Dianne Hackborn1655be42009-05-08 14:29:01 -0700187 // The flags that are set for all calls we make to the package manager.
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700188 static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
Dianne Hackborn1655be42009-05-08 14:29:01 -0700189
Dianne Hackbornf02e57b2011-03-01 22:21:04 -0800190 private static final String SYSTEM_DEBUGGABLE = "ro.debuggable";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800191
Dianne Hackborn2a29b3a2012-03-15 15:48:38 -0700192 static final boolean IS_USER_BUILD = "user".equals(Build.TYPE);
193
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800194 // Maximum number of recent tasks that we can remember.
195 static final int MAX_RECENT_TASKS = 20;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700196
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700197 // Amount of time after a call to stopAppSwitches() during which we will
198 // prevent further untrusted switches from happening.
199 static final long APP_SWITCH_DELAY_TIME = 5*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800200
201 // How long we wait for a launched process to attach to the activity manager
202 // before we decide it's never going to come up for real.
203 static final int PROC_START_TIMEOUT = 10*1000;
204
Jeff Brown3f9dd282011-07-08 20:02:19 -0700205 // How long we wait for a launched process to attach to the activity manager
206 // before we decide it's never going to come up for real, when the process was
207 // started with a wrapper for instrumentation (such as Valgrind) because it
208 // could take much longer than usual.
209 static final int PROC_START_TIMEOUT_WITH_WRAPPER = 300*1000;
210
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800211 // How long to wait after going idle before forcing apps to GC.
212 static final int GC_TIMEOUT = 5*1000;
213
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700214 // The minimum amount of time between successive GC requests for a process.
215 static final int GC_MIN_INTERVAL = 60*1000;
216
Dianne Hackborn287952c2010-09-22 22:34:31 -0700217 // The rate at which we check for apps using excessive power -- 15 mins.
218 static final int POWER_CHECK_DELAY = (DEBUG_POWER_QUICK ? 2 : 15) * 60*1000;
219
220 // The minimum sample duration we will allow before deciding we have
221 // enough data on wake locks to start killing things.
222 static final int WAKE_LOCK_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
223
224 // The minimum sample duration we will allow before deciding we have
225 // enough data on CPU usage to start killing things.
226 static final int CPU_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700227
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800228 // How long we allow a receiver to run before giving up on it.
229 static final int BROADCAST_TIMEOUT = 10*1000;
230
231 // How long we wait for a service to finish executing.
232 static final int SERVICE_TIMEOUT = 20*1000;
233
234 // How long a service needs to be running until restarting its process
235 // is no longer considered to be a relaunch of the service.
236 static final int SERVICE_RESTART_DURATION = 5*1000;
237
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700238 // How long a service needs to be running until it will start back at
239 // SERVICE_RESTART_DURATION after being killed.
240 static final int SERVICE_RESET_RUN_DURATION = 60*1000;
241
242 // Multiplying factor to increase restart duration time by, for each time
243 // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
244 static final int SERVICE_RESTART_DURATION_FACTOR = 4;
245
246 // The minimum amount of time between restarting services that we allow.
247 // That is, when multiple services are restarting, we won't allow each
248 // to restart less than this amount of time from the last one.
249 static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
250
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800251 // Maximum amount of time for there to be no activity on a service before
252 // we consider it non-essential and allow its process to go on the
253 // LRU background list.
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700254 static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800255
256 // How long we wait until we timeout on key dispatching.
257 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
258
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800259 // How long we wait until we timeout on key dispatching during instrumentation.
260 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
261
Dan Egnor42471dd2010-01-07 17:25:22 -0800262 static final int MY_PID = Process.myPid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800263
264 static final String[] EMPTY_STRING_ARRAY = new String[0];
265
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700266 public ActivityStack mMainStack;
Mike Lockwooda0a8b242011-08-12 13:55:22 -0700267
268 private final boolean mHeadless;
269
Joe Onoratoe332aa12011-11-02 20:50:08 -0700270 // Whether we should show our dialogs (ANR, crash, etc) or just perform their
271 // default actuion automatically. Important for devices without direct input
272 // devices.
273 private boolean mShowDialogs = true;
274
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800275 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700276 * Description of a request to start a new activity, which has been held
277 * due to app switches being disabled.
278 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700279 static class PendingActivityLaunch {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700280 ActivityRecord r;
281 ActivityRecord sourceRecord;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700282 Uri[] grantedUriPermissions;
283 int grantedMode;
284 boolean onlyIfNeeded;
285 }
286
287 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
288 = new ArrayList<PendingActivityLaunch>();
289
290 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800291 * List of all active broadcasts that are to be executed immediately
292 * (without waiting for another broadcast to finish). Currently this only
293 * contains broadcasts to registered receivers, to avoid spinning up
294 * a bunch of processes to execute IntentReceiver components.
295 */
296 final ArrayList<BroadcastRecord> mParallelBroadcasts
297 = new ArrayList<BroadcastRecord>();
298
299 /**
300 * List of all active broadcasts that are to be executed one at a time.
301 * The object at the top of the list is the currently activity broadcasts;
302 * those after it are waiting for the top to finish..
303 */
304 final ArrayList<BroadcastRecord> mOrderedBroadcasts
305 = new ArrayList<BroadcastRecord>();
306
307 /**
Dianne Hackborn12527f92009-11-11 17:39:50 -0800308 * Historical data of past broadcasts, for debugging.
309 */
Dianne Hackborn28695e02011-11-02 21:59:51 -0700310 static final int MAX_BROADCAST_HISTORY = 25;
Dianne Hackborn12527f92009-11-11 17:39:50 -0800311 final BroadcastRecord[] mBroadcastHistory
312 = new BroadcastRecord[MAX_BROADCAST_HISTORY];
313
314 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800315 * Set when we current have a BROADCAST_INTENT_MSG in flight.
316 */
317 boolean mBroadcastsScheduled = false;
318
319 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800320 * Activity we have told the window manager to have key focus.
321 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700322 ActivityRecord mFocusedActivity = null;
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700323 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800324 * List of intents that were used to start the most recent tasks.
325 */
Dianne Hackborn0c5001d2011-04-12 18:16:08 -0700326 final ArrayList<TaskRecord> mRecentTasks = new ArrayList<TaskRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800327
328 /**
Dianne Hackborn7d608422011-08-07 16:24:18 -0700329 * Process management.
330 */
331 final ProcessList mProcessList = new ProcessList();
332
333 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800334 * All of the applications we currently have running organized by name.
335 * The keys are strings of the application package name (as
336 * returned by the package manager), and the keys are ApplicationRecord
337 * objects.
338 */
Dianne Hackborn0c5001d2011-04-12 18:16:08 -0700339 final ProcessMap<ProcessRecord> mProcessNames = new ProcessMap<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800340
341 /**
Dianne Hackborn860755f2010-06-03 18:47:52 -0700342 * The currently running heavy-weight process, if any.
343 */
344 ProcessRecord mHeavyWeightProcess = null;
345
346 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800347 * The last time that various processes have crashed.
348 */
349 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
350
351 /**
352 * Set of applications that we consider to be bad, and will reject
353 * incoming broadcasts from (which the user has no control over).
354 * Processes are added to this set when they have crashed twice within
355 * a minimum amount of time; they are removed from it when they are
356 * later restarted (hopefully due to some user action). The value is the
357 * time it was added to the list.
358 */
359 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
360
361 /**
362 * All of the processes we currently have running organized by pid.
363 * The keys are the pid running the application.
364 *
365 * <p>NOTE: This object is protected by its own lock, NOT the global
366 * activity manager lock!
367 */
Dianne Hackborn0c5001d2011-04-12 18:16:08 -0700368 final SparseArray<ProcessRecord> mPidsSelfLocked = new SparseArray<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800369
370 /**
371 * All of the processes that have been forced to be foreground. The key
372 * is the pid of the caller who requested it (we hold a death
373 * link on it).
374 */
375 abstract class ForegroundToken implements IBinder.DeathRecipient {
376 int pid;
377 IBinder token;
378 }
379 final SparseArray<ForegroundToken> mForegroundProcesses
380 = new SparseArray<ForegroundToken>();
381
382 /**
383 * List of records for processes that someone had tried to start before the
384 * system was ready. We don't start them at that point, but ensure they
385 * are started by the time booting is complete.
386 */
387 final ArrayList<ProcessRecord> mProcessesOnHold
388 = new ArrayList<ProcessRecord>();
389
390 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800391 * List of persistent applications that are in the process
392 * of being started.
393 */
394 final ArrayList<ProcessRecord> mPersistentStartingProcesses
395 = new ArrayList<ProcessRecord>();
396
397 /**
398 * Processes that are being forcibly torn down.
399 */
400 final ArrayList<ProcessRecord> mRemovedProcesses
401 = new ArrayList<ProcessRecord>();
402
403 /**
404 * List of running applications, sorted by recent usage.
405 * The first entry in the list is the least recently used.
406 * It contains ApplicationRecord objects. This list does NOT include
407 * any persistent application records (since we never want to exit them).
408 */
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800409 final ArrayList<ProcessRecord> mLruProcesses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800410 = new ArrayList<ProcessRecord>();
411
412 /**
413 * List of processes that should gc as soon as things are idle.
414 */
415 final ArrayList<ProcessRecord> mProcessesToGc
416 = new ArrayList<ProcessRecord>();
417
418 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -0800419 * This is the process holding what we currently consider to be
420 * the "home" activity.
421 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700422 ProcessRecord mHomeProcess;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800423
424 /**
Dianne Hackbornf35fe232011-11-01 19:25:20 -0700425 * This is the process holding the activity the user last visited that
426 * is in a different process from the one they are currently in.
427 */
428 ProcessRecord mPreviousProcess;
Dianne Hackborn50685602011-12-01 12:23:37 -0800429
430 /**
431 * The time at which the previous process was last visible.
432 */
433 long mPreviousProcessVisibleTime;
434
Dianne Hackbornf35fe232011-11-01 19:25:20 -0700435 /**
Dianne Hackborne2515ee2011-04-27 18:52:56 -0400436 * Packages that the user has asked to have run in screen size
437 * compatibility mode instead of filling the screen.
438 */
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -0700439 final CompatModePackages mCompatModePackages;
Dianne Hackborne2515ee2011-04-27 18:52:56 -0400440
441 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800442 * Set of PendingResultRecord objects that are currently active.
443 */
444 final HashSet mPendingResultRecords = new HashSet();
445
446 /**
447 * Set of IntentSenderRecord objects that are currently active.
448 */
449 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
450 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
451
452 /**
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -0800453 * Fingerprints (hashCode()) of stack traces that we've
Brad Fitzpatrick143666f2010-06-14 12:40:21 -0700454 * already logged DropBox entries for. Guarded by itself. If
455 * something (rogue user app) forces this over
456 * MAX_DUP_SUPPRESSED_STACKS entries, the contents are cleared.
457 */
458 private final HashSet<Integer> mAlreadyLoggedViolatedStacks = new HashSet<Integer>();
459 private static final int MAX_DUP_SUPPRESSED_STACKS = 5000;
460
461 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -0700462 * Strict Mode background batched logging state.
463 *
464 * The string buffer is guarded by itself, and its lock is also
465 * used to determine if another batched write is already
466 * in-flight.
467 */
468 private final StringBuilder mStrictModeBuffer = new StringBuilder();
469
470 /**
Jeff Brown4d94a762010-09-23 11:33:28 -0700471 * True if we have a pending unexpired BROADCAST_TIMEOUT_MSG posted to our handler.
472 */
473 private boolean mPendingBroadcastTimeoutMessage;
474
475 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800476 * Intent broadcast that we have tried to start, but are
477 * waiting for its application's process to be created. We only
478 * need one (instead of a list) because we always process broadcasts
479 * one at a time, so no others can be started while waiting for this
480 * one.
481 */
482 BroadcastRecord mPendingBroadcast = null;
483
484 /**
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700485 * The receiver index that is pending, to restart the broadcast if needed.
486 */
487 int mPendingBroadcastRecvIndex;
488
489 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800490 * Keeps track of all IIntentReceivers that have been registered for
491 * broadcasts. Hash keys are the receiver IBinder, hash value is
492 * a ReceiverList.
493 */
494 final HashMap mRegisteredReceivers = new HashMap();
495
496 /**
497 * Resolver for broadcast intents to registered receivers.
498 * Holds BroadcastFilter (subclass of IntentFilter).
499 */
500 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
501 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
502 @Override
503 protected boolean allowFilterResult(
504 BroadcastFilter filter, List<BroadcastFilter> dest) {
505 IBinder target = filter.receiverList.receiver.asBinder();
506 for (int i=dest.size()-1; i>=0; i--) {
507 if (dest.get(i).receiverList.receiver.asBinder() == target) {
508 return false;
509 }
510 }
511 return true;
512 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -0700513
514 @Override
515 protected String packageForFilter(BroadcastFilter filter) {
516 return filter.packageName;
517 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800518 };
519
520 /**
521 * State of all active sticky broadcasts. Keys are the action of the
522 * sticky Intent, values are an ArrayList of all broadcasted intents with
523 * that action (which should usually be one).
524 */
525 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
526 new HashMap<String, ArrayList<Intent>>();
527
528 /**
529 * All currently running services.
530 */
531 final HashMap<ComponentName, ServiceRecord> mServices =
532 new HashMap<ComponentName, ServiceRecord>();
533
534 /**
535 * All currently running services indexed by the Intent used to start them.
536 */
537 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
538 new HashMap<Intent.FilterComparison, ServiceRecord>();
539
540 /**
541 * All currently bound service connections. Keys are the IBinder of
542 * the client's IServiceConnection.
543 */
Dianne Hackborn43d9ac82010-08-25 15:06:25 -0700544 final HashMap<IBinder, ArrayList<ConnectionRecord>> mServiceConnections
545 = new HashMap<IBinder, ArrayList<ConnectionRecord>>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800546
547 /**
548 * List of services that we have been asked to start,
549 * but haven't yet been able to. It is used to hold start requests
550 * while waiting for their corresponding application thread to get
551 * going.
552 */
553 final ArrayList<ServiceRecord> mPendingServices
554 = new ArrayList<ServiceRecord>();
555
556 /**
557 * List of services that are scheduled to restart following a crash.
558 */
559 final ArrayList<ServiceRecord> mRestartingServices
560 = new ArrayList<ServiceRecord>();
561
562 /**
563 * List of services that are in the process of being stopped.
564 */
565 final ArrayList<ServiceRecord> mStoppingServices
566 = new ArrayList<ServiceRecord>();
567
568 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700569 * Backup/restore process management
570 */
571 String mBackupAppName = null;
572 BackupRecord mBackupTarget = null;
573
574 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800575 * List of PendingThumbnailsRecord objects of clients who are still
576 * waiting to receive all of the thumbnails for a task.
577 */
578 final ArrayList mPendingThumbnails = new ArrayList();
579
580 /**
581 * List of HistoryRecord objects that have been finished and must
582 * still report back to a pending thumbnail receiver.
583 */
584 final ArrayList mCancelledThumbnails = new ArrayList();
585
586 /**
587 * All of the currently running global content providers. Keys are a
588 * string containing the provider name and values are a
589 * ContentProviderRecord object containing the data about it. Note
590 * that a single provider may be published under multiple names, so
591 * there may be multiple entries here for a single one in mProvidersByClass.
592 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700593 final HashMap<String, ContentProviderRecord> mProvidersByName
594 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800595
596 /**
597 * All of the currently running global content providers. Keys are a
598 * string containing the provider's implementation class and values are a
599 * ContentProviderRecord object containing the data about it.
600 */
Dianne Hackborn1c9b2602011-08-19 14:08:43 -0700601 final HashMap<ComponentName, ContentProviderRecord> mProvidersByClass
602 = new HashMap<ComponentName, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800603
604 /**
605 * List of content providers who have clients waiting for them. The
606 * application is currently being launched and the provider will be
607 * removed from this list once it is published.
608 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700609 final ArrayList<ContentProviderRecord> mLaunchingProviders
610 = new ArrayList<ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800611
612 /**
613 * Global set of specific Uri permissions that have been granted.
614 */
615 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
616 = new SparseArray<HashMap<Uri, UriPermission>>();
617
Svetoslav Ganov54d068e2011-03-02 12:58:40 -0800618 CoreSettingsObserver mCoreSettingsObserver;
619
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800620 /**
621 * Thread-local storage used to carry caller permissions over through
622 * indirect content-provider access.
623 * @see #ActivityManagerService.openContentUri()
624 */
625 private class Identity {
626 public int pid;
627 public int uid;
628
629 Identity(int _pid, int _uid) {
630 pid = _pid;
631 uid = _uid;
632 }
633 }
634 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
635
636 /**
637 * All information we have collected about the runtime performance of
638 * any user id that can impact battery performance.
639 */
640 final BatteryStatsService mBatteryStatsService;
641
642 /**
643 * information about component usage
644 */
645 final UsageStatsService mUsageStatsService;
646
647 /**
648 * Current configuration information. HistoryRecord objects are given
649 * a reference to this object to indicate which configuration they are
650 * currently running in, so this object must be kept immutable.
651 */
652 Configuration mConfiguration = new Configuration();
653
654 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800655 * Current sequencing integer of the configuration, for skipping old
656 * configurations.
657 */
658 int mConfigurationSeq = 0;
659
660 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700661 * Hardware-reported OpenGLES version.
662 */
663 final int GL_ES_VERSION;
664
665 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800666 * List of initialization arguments to pass to all processes when binding applications to them.
667 * For example, references to the commonly used services.
668 */
669 HashMap<String, IBinder> mAppBindArgs;
670
671 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700672 * Temporary to avoid allocations. Protected by main lock.
673 */
674 final StringBuilder mStringBuilder = new StringBuilder(256);
675
676 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800677 * Used to control how we initialize the service.
678 */
679 boolean mStartRunning = false;
680 ComponentName mTopComponent;
681 String mTopAction;
682 String mTopData;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700683 boolean mProcessesReady = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800684 boolean mSystemReady = false;
685 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700686 boolean mWaitingUpdate = false;
687 boolean mDidUpdate = false;
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700688 boolean mOnBattery = false;
Dianne Hackborn0dad3642010-09-09 21:25:35 -0700689 boolean mLaunchWarningShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800690
691 Context mContext;
692
693 int mFactoryTest;
694
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700695 boolean mCheckedForSetup;
696
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800697 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700698 * The time at which we will allow normal application switches again,
699 * after a call to {@link #stopAppSwitches()}.
700 */
701 long mAppSwitchesAllowedTime;
702
703 /**
704 * This is set to true after the first switch after mAppSwitchesAllowedTime
705 * is set; any switches after that will clear the time.
706 */
707 boolean mDidAppSwitch;
708
709 /**
Dianne Hackborn287952c2010-09-22 22:34:31 -0700710 * Last time (in realtime) at which we checked for power usage.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700711 */
Dianne Hackborn287952c2010-09-22 22:34:31 -0700712 long mLastPowerCheckRealtime;
713
714 /**
715 * Last time (in uptime) at which we checked for power usage.
716 */
717 long mLastPowerCheckUptime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700718
719 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800720 * Set while we are wanting to sleep, to prevent any
721 * activities from being started/resumed.
722 */
723 boolean mSleeping = false;
724
725 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700726 * Set if we are shutting down the system, similar to sleeping.
727 */
728 boolean mShuttingDown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800729
730 /**
731 * Task identifier that activities are currently being started
732 * in. Incremented each time a new task is created.
733 * todo: Replace this with a TokenSpace class that generates non-repeating
734 * integers that won't wrap.
735 */
736 int mCurTask = 1;
737
738 /**
739 * Current sequence id for oom_adj computation traversal.
740 */
741 int mAdjSeq = 0;
742
743 /**
Dianne Hackborn906497c2010-05-10 15:57:38 -0700744 * Current sequence id for process LRU updating.
745 */
746 int mLruSeq = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800747
748 /**
Dianne Hackborne02c88a2011-10-28 13:58:15 -0700749 * Keep track of the number of service processes we last found, to
750 * determine on the next iteration which should be B services.
751 */
752 int mNumServiceProcs = 0;
753 int mNewNumServiceProcs = 0;
754
755 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800756 * System monitoring: number of processes that died since the last
757 * N procs were started.
758 */
759 int[] mProcDeaths = new int[20];
760
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700761 /**
762 * This is set if we had to do a delayed dexopt of an app before launching
763 * it, to increasing the ANR timeouts in that case.
764 */
765 boolean mDidDexOpt;
766
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800767 String mDebugApp = null;
768 boolean mWaitForDebugger = false;
769 boolean mDebugTransient = false;
770 String mOrigDebugApp = null;
771 boolean mOrigWaitForDebugger = false;
772 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700773 IActivityController mController = null;
Dianne Hackborn62f20ec2011-08-15 17:40:28 -0700774 String mProfileApp = null;
775 ProcessRecord mProfileProc = null;
776 String mProfileFile;
777 ParcelFileDescriptor mProfileFd;
778 int mProfileType = 0;
779 boolean mAutoStopProfiler = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800780
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700781 final RemoteCallbackList<IActivityWatcher> mWatchers
782 = new RemoteCallbackList<IActivityWatcher>();
Jeff Sharkeya4620792011-05-20 15:29:23 -0700783
784 final RemoteCallbackList<IProcessObserver> mProcessObservers
785 = new RemoteCallbackList<IProcessObserver>();
786
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800787 /**
788 * Callback of last caller to {@link #requestPss}.
789 */
790 Runnable mRequestPssCallback;
791
792 /**
793 * Remaining processes for which we are waiting results from the last
794 * call to {@link #requestPss}.
795 */
796 final ArrayList<ProcessRecord> mRequestPssList
797 = new ArrayList<ProcessRecord>();
798
799 /**
800 * Runtime statistics collection thread. This object's lock is used to
801 * protect all related state.
802 */
803 final Thread mProcessStatsThread;
804
805 /**
806 * Used to collect process stats when showing not responding dialog.
807 * Protected by mProcessStatsThread.
808 */
809 final ProcessStats mProcessStats = new ProcessStats(
810 MONITOR_THREAD_CPU_USAGE);
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700811 final AtomicLong mLastCpuTime = new AtomicLong(0);
812 final AtomicBoolean mProcessStatsMutexFree = new AtomicBoolean(true);
813
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800814 long mLastWriteTime = 0;
815
816 /**
Christopher Tate9ce685b2012-03-15 16:27:14 -0700817 * Used to retain an update lock when the foreground activity is in
818 * immersive mode.
819 */
820 final UpdateLock mUpdateLock = new UpdateLock("immersive");
821
822 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800823 * Set to true after the system has finished booting.
824 */
825 boolean mBooted = false;
826
Dianne Hackborn7d608422011-08-07 16:24:18 -0700827 int mProcessLimit = ProcessList.MAX_HIDDEN_APPS;
Dianne Hackbornce86ba82011-07-13 19:33:41 -0700828 int mProcessLimitOverride = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800829
830 WindowManagerService mWindowManager;
831
832 static ActivityManagerService mSelf;
833 static ActivityThread mSystemThread;
834
835 private final class AppDeathRecipient implements IBinder.DeathRecipient {
836 final ProcessRecord mApp;
837 final int mPid;
838 final IApplicationThread mAppThread;
839
840 AppDeathRecipient(ProcessRecord app, int pid,
841 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800842 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800843 TAG, "New death recipient " + this
844 + " for thread " + thread.asBinder());
845 mApp = app;
846 mPid = pid;
847 mAppThread = thread;
848 }
849
850 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800851 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800852 TAG, "Death received in " + this
853 + " for thread " + mAppThread.asBinder());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800854 synchronized(ActivityManagerService.this) {
855 appDiedLocked(mApp, mPid, mAppThread);
856 }
857 }
858 }
859
860 static final int SHOW_ERROR_MSG = 1;
861 static final int SHOW_NOT_RESPONDING_MSG = 2;
862 static final int SHOW_FACTORY_ERROR_MSG = 3;
863 static final int UPDATE_CONFIGURATION_MSG = 4;
864 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
865 static final int WAIT_FOR_DEBUGGER_MSG = 6;
866 static final int BROADCAST_INTENT_MSG = 7;
867 static final int BROADCAST_TIMEOUT_MSG = 8;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800868 static final int SERVICE_TIMEOUT_MSG = 12;
869 static final int UPDATE_TIME_ZONE = 13;
870 static final int SHOW_UID_ERROR_MSG = 14;
871 static final int IM_FEELING_LUCKY_MSG = 15;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800872 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700873 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -0700874 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800875 static final int FINALIZE_PENDING_INTENT_MSG = 23;
Dianne Hackborn860755f2010-06-03 18:47:52 -0700876 static final int POST_HEAVY_NOTIFICATION_MSG = 24;
877 static final int CANCEL_HEAVY_NOTIFICATION_MSG = 25;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700878 static final int SHOW_STRICT_MODE_VIOLATION_MSG = 26;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700879 static final int CHECK_EXCESSIVE_WAKE_LOCKS_MSG = 27;
Robert Greenwalt03595d02010-11-02 14:08:23 -0700880 static final int CLEAR_DNS_CACHE = 28;
Robert Greenwalt434203a2010-10-11 16:00:27 -0700881 static final int UPDATE_HTTP_PROXY = 29;
Dianne Hackborn36cd41f2011-05-25 21:00:46 -0700882 static final int SHOW_COMPAT_MODE_DIALOG_MSG = 30;
Dianne Hackborn36f80f32011-05-31 18:26:45 -0700883 static final int DISPATCH_FOREGROUND_ACTIVITIES_CHANGED = 31;
884 static final int DISPATCH_PROCESS_DIED = 32;
Dianne Hackborn04d6db32011-11-04 20:07:24 -0700885 static final int REPORT_MEM_USAGE = 33;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800886
887 AlertDialog mUidAlert;
Dianne Hackborn36cd41f2011-05-25 21:00:46 -0700888 CompatModeDialog mCompatModeDialog;
Dianne Hackborn04d6db32011-11-04 20:07:24 -0700889 long mLastMemUsageReportTime = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800890
891 final Handler mHandler = new Handler() {
892 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800893 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800894 //}
895
896 public void handleMessage(Message msg) {
897 switch (msg.what) {
898 case SHOW_ERROR_MSG: {
899 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800900 synchronized (ActivityManagerService.this) {
901 ProcessRecord proc = (ProcessRecord)data.get("app");
902 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800903 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800904 return;
905 }
906 AppErrorResult res = (AppErrorResult) data.get("result");
Joe Onoratoe332aa12011-11-02 20:50:08 -0700907 if (mShowDialogs && !mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -0800908 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800909 d.show();
910 proc.crashDialog = d;
911 } else {
912 // The device is asleep, so just pretend that the user
913 // saw a crash dialog and hit "force quit".
914 res.set(0);
915 }
916 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700917
918 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800919 } break;
920 case SHOW_NOT_RESPONDING_MSG: {
921 synchronized (ActivityManagerService.this) {
922 HashMap data = (HashMap) msg.obj;
923 ProcessRecord proc = (ProcessRecord)data.get("app");
924 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800925 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800926 return;
927 }
The Android Open Source Project4df24232009-03-05 14:34:35 -0800928
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700929 Intent intent = new Intent("android.intent.action.ANR");
930 if (!mProcessesReady) {
931 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
932 }
933 broadcastIntentLocked(null, null, intent,
The Android Open Source Project4df24232009-03-05 14:34:35 -0800934 null, null, 0, null, null, null,
935 false, false, MY_PID, Process.SYSTEM_UID);
Justin Kohbc52ca22012-03-29 15:11:44 -0700936 if (mShowDialogs) {
937 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
938 mContext, proc, (ActivityRecord) data.get("activity"));
939 d.show();
940 proc.anrDialog = d;
941 } else {
942 // Just kill the app if there is no dialog to be shown.
943 killAppAtUsersRequest(proc, null);
944 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800945 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700946
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700947 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800948 } break;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700949 case SHOW_STRICT_MODE_VIOLATION_MSG: {
950 HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
951 synchronized (ActivityManagerService.this) {
952 ProcessRecord proc = (ProcessRecord) data.get("app");
953 if (proc == null) {
954 Slog.e(TAG, "App not found when showing strict mode dialog.");
955 break;
956 }
957 if (proc.crashDialog != null) {
958 Slog.e(TAG, "App already has strict mode dialog: " + proc);
959 return;
960 }
961 AppErrorResult res = (AppErrorResult) data.get("result");
Joe Onoratoe332aa12011-11-02 20:50:08 -0700962 if (mShowDialogs && !mSleeping && !mShuttingDown) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700963 Dialog d = new StrictModeViolationDialog(mContext, res, proc);
964 d.show();
965 proc.crashDialog = d;
966 } else {
967 // The device is asleep, so just pretend that the user
968 // saw a crash dialog and hit "force quit".
969 res.set(0);
970 }
971 }
972 ensureBootCompleted();
973 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800974 case SHOW_FACTORY_ERROR_MSG: {
975 Dialog d = new FactoryErrorDialog(
976 mContext, msg.getData().getCharSequence("msg"));
977 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700978 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800979 } break;
980 case UPDATE_CONFIGURATION_MSG: {
981 final ContentResolver resolver = mContext.getContentResolver();
982 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
983 } break;
984 case GC_BACKGROUND_PROCESSES_MSG: {
985 synchronized (ActivityManagerService.this) {
986 performAppGcsIfAppropriateLocked();
987 }
988 } break;
989 case WAIT_FOR_DEBUGGER_MSG: {
990 synchronized (ActivityManagerService.this) {
991 ProcessRecord app = (ProcessRecord)msg.obj;
992 if (msg.arg1 != 0) {
993 if (!app.waitedForDebugger) {
994 Dialog d = new AppWaitingForDebuggerDialog(
995 ActivityManagerService.this,
996 mContext, app);
997 app.waitDialog = d;
998 app.waitedForDebugger = true;
999 d.show();
1000 }
1001 } else {
1002 if (app.waitDialog != null) {
1003 app.waitDialog.dismiss();
1004 app.waitDialog = null;
1005 }
1006 }
1007 }
1008 } break;
1009 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001010 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001011 TAG, "Received BROADCAST_INTENT_MSG");
1012 processNextBroadcast(true);
1013 } break;
1014 case BROADCAST_TIMEOUT_MSG: {
Jeff Brown4d94a762010-09-23 11:33:28 -07001015 synchronized (ActivityManagerService.this) {
1016 broadcastTimeoutLocked(true);
Jeff Hamiltonacf84742010-05-25 22:10:18 -05001017 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001018 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001019 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001020 if (mDidDexOpt) {
1021 mDidDexOpt = false;
1022 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1023 nmsg.obj = msg.obj;
1024 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1025 return;
1026 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001027 serviceTimeout((ProcessRecord)msg.obj);
1028 } break;
1029 case UPDATE_TIME_ZONE: {
1030 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001031 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1032 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001033 if (r.thread != null) {
1034 try {
1035 r.thread.updateTimeZone();
1036 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001037 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001038 }
1039 }
1040 }
1041 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001042 } break;
Robert Greenwalt03595d02010-11-02 14:08:23 -07001043 case CLEAR_DNS_CACHE: {
1044 synchronized (ActivityManagerService.this) {
1045 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1046 ProcessRecord r = mLruProcesses.get(i);
1047 if (r.thread != null) {
1048 try {
1049 r.thread.clearDnsCache();
1050 } catch (RemoteException ex) {
1051 Slog.w(TAG, "Failed to clear dns cache for: " + r.info.processName);
1052 }
1053 }
1054 }
1055 }
1056 } break;
Robert Greenwalt434203a2010-10-11 16:00:27 -07001057 case UPDATE_HTTP_PROXY: {
1058 ProxyProperties proxy = (ProxyProperties)msg.obj;
1059 String host = "";
1060 String port = "";
1061 String exclList = "";
1062 if (proxy != null) {
1063 host = proxy.getHost();
1064 port = Integer.toString(proxy.getPort());
1065 exclList = proxy.getExclusionList();
1066 }
1067 synchronized (ActivityManagerService.this) {
1068 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1069 ProcessRecord r = mLruProcesses.get(i);
1070 if (r.thread != null) {
1071 try {
1072 r.thread.setHttpProxy(host, port, exclList);
1073 } catch (RemoteException ex) {
1074 Slog.w(TAG, "Failed to update http proxy for: " +
1075 r.info.processName);
1076 }
1077 }
1078 }
1079 }
1080 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001081 case SHOW_UID_ERROR_MSG: {
Joe Onoratoe332aa12011-11-02 20:50:08 -07001082 String title = "System UIDs Inconsistent";
1083 String text = "UIDs on the system are inconsistent, you need to wipe your"
1084 + " data partition or your device will be unstable.";
1085 Log.e(TAG, title + ": " + text);
1086 if (mShowDialogs) {
1087 // XXX This is a temporary dialog, no need to localize.
1088 AlertDialog d = new BaseErrorDialog(mContext);
1089 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1090 d.setCancelable(false);
1091 d.setTitle(title);
1092 d.setMessage(text);
1093 d.setButton(DialogInterface.BUTTON_POSITIVE, "I'm Feeling Lucky",
1094 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1095 mUidAlert = d;
1096 d.show();
1097 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001098 } break;
1099 case IM_FEELING_LUCKY_MSG: {
1100 if (mUidAlert != null) {
1101 mUidAlert.dismiss();
1102 mUidAlert = null;
1103 }
1104 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001105 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001106 if (mDidDexOpt) {
1107 mDidDexOpt = false;
1108 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1109 nmsg.obj = msg.obj;
1110 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1111 return;
1112 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001113 ProcessRecord app = (ProcessRecord)msg.obj;
1114 synchronized (ActivityManagerService.this) {
1115 processStartTimedOutLocked(app);
1116 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001117 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001118 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1119 synchronized (ActivityManagerService.this) {
1120 doPendingActivityLaunchesLocked(true);
1121 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001122 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001123 case KILL_APPLICATION_MSG: {
1124 synchronized (ActivityManagerService.this) {
1125 int uid = msg.arg1;
1126 boolean restart = (msg.arg2 == 1);
1127 String pkg = (String) msg.obj;
Christopher Tate3dacd842011-08-19 14:56:15 -07001128 forceStopPackageLocked(pkg, uid, restart, false, true, false);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001129 }
1130 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001131 case FINALIZE_PENDING_INTENT_MSG: {
1132 ((PendingIntentRecord)msg.obj).completeFinalize();
1133 } break;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001134 case POST_HEAVY_NOTIFICATION_MSG: {
1135 INotificationManager inm = NotificationManager.getService();
1136 if (inm == null) {
1137 return;
1138 }
1139
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001140 ActivityRecord root = (ActivityRecord)msg.obj;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001141 ProcessRecord process = root.app;
1142 if (process == null) {
1143 return;
1144 }
1145
1146 try {
1147 Context context = mContext.createPackageContext(process.info.packageName, 0);
1148 String text = mContext.getString(R.string.heavy_weight_notification,
1149 context.getApplicationInfo().loadLabel(context.getPackageManager()));
1150 Notification notification = new Notification();
1151 notification.icon = com.android.internal.R.drawable.stat_sys_adb; //context.getApplicationInfo().icon;
1152 notification.when = 0;
1153 notification.flags = Notification.FLAG_ONGOING_EVENT;
1154 notification.tickerText = text;
1155 notification.defaults = 0; // please be quiet
1156 notification.sound = null;
1157 notification.vibrate = null;
1158 notification.setLatestEventInfo(context, text,
1159 mContext.getText(R.string.heavy_weight_notification_detail),
1160 PendingIntent.getActivity(mContext, 0, root.intent,
1161 PendingIntent.FLAG_CANCEL_CURRENT));
1162
1163 try {
1164 int[] outId = new int[1];
1165 inm.enqueueNotification("android", R.string.heavy_weight_notification,
1166 notification, outId);
1167 } catch (RuntimeException e) {
1168 Slog.w(ActivityManagerService.TAG,
1169 "Error showing notification for heavy-weight app", e);
1170 } catch (RemoteException e) {
1171 }
1172 } catch (NameNotFoundException e) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07001173 Slog.w(TAG, "Unable to create context for heavy notification", e);
Dianne Hackborn860755f2010-06-03 18:47:52 -07001174 }
1175 } break;
1176 case CANCEL_HEAVY_NOTIFICATION_MSG: {
1177 INotificationManager inm = NotificationManager.getService();
1178 if (inm == null) {
1179 return;
1180 }
1181 try {
1182 inm.cancelNotification("android",
1183 R.string.heavy_weight_notification);
1184 } catch (RuntimeException e) {
1185 Slog.w(ActivityManagerService.TAG,
1186 "Error canceling notification for service", e);
1187 } catch (RemoteException e) {
1188 }
1189 } break;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001190 case CHECK_EXCESSIVE_WAKE_LOCKS_MSG: {
1191 synchronized (ActivityManagerService.this) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001192 checkExcessivePowerUsageLocked(true);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -07001193 removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001194 Message nmsg = obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
1195 sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001196 }
1197 } break;
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07001198 case SHOW_COMPAT_MODE_DIALOG_MSG: {
1199 synchronized (ActivityManagerService.this) {
1200 ActivityRecord ar = (ActivityRecord)msg.obj;
1201 if (mCompatModeDialog != null) {
1202 if (mCompatModeDialog.mAppInfo.packageName.equals(
1203 ar.info.applicationInfo.packageName)) {
1204 return;
1205 }
1206 mCompatModeDialog.dismiss();
1207 mCompatModeDialog = null;
1208 }
Dianne Hackborn29478262011-06-07 15:44:22 -07001209 if (ar != null && false) {
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07001210 if (mCompatModePackages.getPackageAskCompatModeLocked(
1211 ar.packageName)) {
1212 int mode = mCompatModePackages.computeCompatModeLocked(
1213 ar.info.applicationInfo);
1214 if (mode == ActivityManager.COMPAT_MODE_DISABLED
1215 || mode == ActivityManager.COMPAT_MODE_ENABLED) {
1216 mCompatModeDialog = new CompatModeDialog(
1217 ActivityManagerService.this, mContext,
1218 ar.info.applicationInfo);
1219 mCompatModeDialog.show();
1220 }
1221 }
1222 }
1223 }
Dianne Hackborn36f80f32011-05-31 18:26:45 -07001224 break;
1225 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07001226 case DISPATCH_FOREGROUND_ACTIVITIES_CHANGED: {
Jeff Sharkey287bd832011-05-28 19:36:26 -07001227 final int pid = msg.arg1;
1228 final int uid = msg.arg2;
1229 final boolean foregroundActivities = (Boolean) msg.obj;
1230 dispatchForegroundActivitiesChanged(pid, uid, foregroundActivities);
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07001231 break;
1232 }
1233 case DISPATCH_PROCESS_DIED: {
Jeff Sharkey287bd832011-05-28 19:36:26 -07001234 final int pid = msg.arg1;
1235 final int uid = msg.arg2;
1236 dispatchProcessDied(pid, uid);
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07001237 break;
1238 }
Dianne Hackborn04d6db32011-11-04 20:07:24 -07001239 case REPORT_MEM_USAGE: {
1240 boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
1241 if (!isDebuggable) {
1242 return;
1243 }
1244 synchronized (ActivityManagerService.this) {
1245 long now = SystemClock.uptimeMillis();
Dianne Hackborn7aa6d312011-11-15 15:01:14 -08001246 if (now < (mLastMemUsageReportTime+5*60*1000)) {
1247 // Don't report more than every 5 minutes to somewhat
Dianne Hackborn04d6db32011-11-04 20:07:24 -07001248 // avoid spamming.
1249 return;
1250 }
1251 mLastMemUsageReportTime = now;
1252 }
1253 Thread thread = new Thread() {
1254 @Override public void run() {
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08001255 StringBuilder dropBuilder = new StringBuilder(1024);
1256 StringBuilder logBuilder = new StringBuilder(1024);
Dianne Hackborn672342c2011-11-29 11:29:02 -08001257 StringWriter oomSw = new StringWriter();
1258 PrintWriter oomPw = new PrintWriter(oomSw);
1259 StringWriter catSw = new StringWriter();
1260 PrintWriter catPw = new PrintWriter(catSw);
1261 String[] emptyArgs = new String[] { };
1262 StringBuilder tag = new StringBuilder(128);
1263 StringBuilder stack = new StringBuilder(128);
1264 tag.append("Low on memory -- ");
1265 dumpApplicationMemoryUsage(null, oomPw, " ", emptyArgs, true, catPw,
1266 tag, stack);
1267 dropBuilder.append(stack);
1268 dropBuilder.append('\n');
1269 dropBuilder.append('\n');
1270 String oomString = oomSw.toString();
1271 dropBuilder.append(oomString);
1272 dropBuilder.append('\n');
1273 logBuilder.append(oomString);
Dianne Hackborn04d6db32011-11-04 20:07:24 -07001274 try {
1275 java.lang.Process proc = Runtime.getRuntime().exec(new String[] {
1276 "procrank", });
1277 final InputStreamReader converter = new InputStreamReader(
1278 proc.getInputStream());
1279 BufferedReader in = new BufferedReader(converter);
1280 String line;
1281 while (true) {
1282 line = in.readLine();
1283 if (line == null) {
1284 break;
1285 }
1286 if (line.length() > 0) {
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08001287 logBuilder.append(line);
1288 logBuilder.append('\n');
Dianne Hackborn04d6db32011-11-04 20:07:24 -07001289 }
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08001290 dropBuilder.append(line);
1291 dropBuilder.append('\n');
Dianne Hackborn04d6db32011-11-04 20:07:24 -07001292 }
1293 converter.close();
1294 } catch (IOException e) {
1295 }
Dianne Hackborn7aa6d312011-11-15 15:01:14 -08001296 synchronized (ActivityManagerService.this) {
Dianne Hackborn672342c2011-11-29 11:29:02 -08001297 catPw.println();
Dianne Hackbornee9aef02011-11-16 13:21:46 -08001298 dumpProcessesLocked(null, catPw, emptyArgs, 0, false, null);
Dianne Hackborn7aa6d312011-11-15 15:01:14 -08001299 catPw.println();
Dianne Hackbornee9aef02011-11-16 13:21:46 -08001300 dumpServicesLocked(null, catPw, emptyArgs, 0, false, false, null);
Dianne Hackborn7aa6d312011-11-15 15:01:14 -08001301 catPw.println();
Dianne Hackbornee9aef02011-11-16 13:21:46 -08001302 dumpActivitiesLocked(null, catPw, emptyArgs, 0, false, false, null);
Dianne Hackborn7aa6d312011-11-15 15:01:14 -08001303 }
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08001304 dropBuilder.append(catSw.toString());
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -08001305 addErrorToDropBox("lowmem", null, "system_server", null,
1306 null, tag.toString(), dropBuilder.toString(), null, null);
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08001307 Slog.i(TAG, logBuilder.toString());
Dianne Hackborn04d6db32011-11-04 20:07:24 -07001308 synchronized (ActivityManagerService.this) {
1309 long now = SystemClock.uptimeMillis();
1310 if (mLastMemUsageReportTime < now) {
1311 mLastMemUsageReportTime = now;
1312 }
1313 }
1314 }
1315 };
1316 thread.start();
1317 break;
1318 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001319 }
1320 }
1321 };
1322
1323 public static void setSystemProcess() {
1324 try {
1325 ActivityManagerService m = mSelf;
1326
1327 ServiceManager.addService("activity", m);
1328 ServiceManager.addService("meminfo", new MemBinder(m));
Chet Haase9c1e23b2011-03-24 10:51:31 -07001329 ServiceManager.addService("gfxinfo", new GraphicsBinder(m));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001330 if (MONITOR_CPU_USAGE) {
1331 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1332 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001333 ServiceManager.addService("permission", new PermissionController(m));
1334
1335 ApplicationInfo info =
1336 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001337 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001338 mSystemThread.installSystemApplicationInfo(info);
1339
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001340 synchronized (mSelf) {
1341 ProcessRecord app = mSelf.newProcessRecordLocked(
1342 mSystemThread.getApplicationThread(), info,
1343 info.processName);
1344 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001345 app.pid = MY_PID;
Dianne Hackborn7d608422011-08-07 16:24:18 -07001346 app.maxAdj = ProcessList.SYSTEM_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001347 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1348 synchronized (mSelf.mPidsSelfLocked) {
1349 mSelf.mPidsSelfLocked.put(app.pid, app);
1350 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001351 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001352 }
1353 } catch (PackageManager.NameNotFoundException e) {
1354 throw new RuntimeException(
1355 "Unable to find android system package", e);
1356 }
1357 }
1358
1359 public void setWindowManager(WindowManagerService wm) {
1360 mWindowManager = wm;
1361 }
1362
1363 public static final Context main(int factoryTest) {
1364 AThread thr = new AThread();
1365 thr.start();
1366
1367 synchronized (thr) {
1368 while (thr.mService == null) {
1369 try {
1370 thr.wait();
1371 } catch (InterruptedException e) {
1372 }
1373 }
1374 }
1375
1376 ActivityManagerService m = thr.mService;
1377 mSelf = m;
1378 ActivityThread at = ActivityThread.systemMain();
1379 mSystemThread = at;
1380 Context context = at.getSystemContext();
Dianne Hackborn247fe742011-01-08 17:25:57 -08001381 context.setTheme(android.R.style.Theme_Holo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001382 m.mContext = context;
1383 m.mFactoryTest = factoryTest;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001384 m.mMainStack = new ActivityStack(m, context, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001385
1386 m.mBatteryStatsService.publish(context);
1387 m.mUsageStatsService.publish(context);
1388
1389 synchronized (thr) {
1390 thr.mReady = true;
1391 thr.notifyAll();
1392 }
1393
1394 m.startRunning(null, null, null, null);
1395
1396 return context;
1397 }
1398
1399 public static ActivityManagerService self() {
1400 return mSelf;
1401 }
1402
1403 static class AThread extends Thread {
1404 ActivityManagerService mService;
1405 boolean mReady = false;
1406
1407 public AThread() {
1408 super("ActivityManager");
1409 }
1410
1411 public void run() {
1412 Looper.prepare();
1413
1414 android.os.Process.setThreadPriority(
1415 android.os.Process.THREAD_PRIORITY_FOREGROUND);
Christopher Tate160edb32010-06-30 17:46:30 -07001416 android.os.Process.setCanSelfBackground(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001417
1418 ActivityManagerService m = new ActivityManagerService();
1419
1420 synchronized (this) {
1421 mService = m;
1422 notifyAll();
1423 }
1424
1425 synchronized (this) {
1426 while (!mReady) {
1427 try {
1428 wait();
1429 } catch (InterruptedException e) {
1430 }
1431 }
1432 }
1433
Brad Fitzpatrickec062f62010-11-03 09:56:54 -07001434 // For debug builds, log event loop stalls to dropbox for analysis.
1435 if (StrictMode.conditionallyEnableDebugLogging()) {
1436 Slog.i(TAG, "Enabled StrictMode logging for AThread's Looper");
1437 }
1438
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001439 Looper.loop();
1440 }
1441 }
1442
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001443 static class MemBinder extends Binder {
1444 ActivityManagerService mActivityManagerService;
1445 MemBinder(ActivityManagerService activityManagerService) {
1446 mActivityManagerService = activityManagerService;
1447 }
1448
1449 @Override
1450 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Kenny Root3abd75b2011-09-29 11:00:41 -07001451 if (mActivityManagerService.checkCallingPermission(android.Manifest.permission.DUMP)
1452 != PackageManager.PERMISSION_GRANTED) {
1453 pw.println("Permission Denial: can't dump meminfo from from pid="
1454 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
1455 + " without permission " + android.Manifest.permission.DUMP);
1456 return;
1457 }
1458
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -08001459 mActivityManagerService.dumpApplicationMemoryUsage(fd, pw, " ", args,
Dianne Hackborn672342c2011-11-29 11:29:02 -08001460 false, null, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001461 }
1462 }
1463
Chet Haase9c1e23b2011-03-24 10:51:31 -07001464 static class GraphicsBinder extends Binder {
1465 ActivityManagerService mActivityManagerService;
1466 GraphicsBinder(ActivityManagerService activityManagerService) {
1467 mActivityManagerService = activityManagerService;
1468 }
1469
1470 @Override
1471 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Kenny Root3abd75b2011-09-29 11:00:41 -07001472 if (mActivityManagerService.checkCallingPermission(android.Manifest.permission.DUMP)
1473 != PackageManager.PERMISSION_GRANTED) {
1474 pw.println("Permission Denial: can't dump gfxinfo from from pid="
1475 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
1476 + " without permission " + android.Manifest.permission.DUMP);
1477 return;
1478 }
1479
Dianne Hackborne17aeb32011-04-07 15:11:57 -07001480 mActivityManagerService.dumpGraphicsHardwareUsage(fd, pw, args);
Chet Haase9c1e23b2011-03-24 10:51:31 -07001481 }
1482 }
1483
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001484 static class CpuBinder extends Binder {
1485 ActivityManagerService mActivityManagerService;
1486 CpuBinder(ActivityManagerService activityManagerService) {
1487 mActivityManagerService = activityManagerService;
1488 }
1489
1490 @Override
1491 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Kenny Root3abd75b2011-09-29 11:00:41 -07001492 if (mActivityManagerService.checkCallingPermission(android.Manifest.permission.DUMP)
1493 != PackageManager.PERMISSION_GRANTED) {
1494 pw.println("Permission Denial: can't dump cpuinfo from from pid="
1495 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
1496 + " without permission " + android.Manifest.permission.DUMP);
1497 return;
1498 }
1499
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001500 synchronized (mActivityManagerService.mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07001501 pw.print(mActivityManagerService.mProcessStats.printCurrentLoad());
1502 pw.print(mActivityManagerService.mProcessStats.printCurrentState(
1503 SystemClock.uptimeMillis()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001504 }
1505 }
1506 }
1507
1508 private ActivityManagerService() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001509 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001510
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001511 File dataDir = Environment.getDataDirectory();
1512 File systemDir = new File(dataDir, "system");
1513 systemDir.mkdirs();
1514 mBatteryStatsService = new BatteryStatsService(new File(
1515 systemDir, "batterystats.bin").toString());
1516 mBatteryStatsService.getActiveStatistics().readLocked();
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001517 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
Dianne Hackborn287952c2010-09-22 22:34:31 -07001518 mOnBattery = DEBUG_POWER ? true
1519 : mBatteryStatsService.getActiveStatistics().getIsOnBattery();
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001520 mBatteryStatsService.getActiveStatistics().setCallback(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001521
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001522 mUsageStatsService = new UsageStatsService(new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001523 systemDir, "usagestats").toString());
Mike Lockwooda0a8b242011-08-12 13:55:22 -07001524 mHeadless = "1".equals(SystemProperties.get("ro.config.headless", "0"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001525
Jack Palevichb90d28c2009-07-22 15:35:24 -07001526 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1527 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1528
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001529 mConfiguration.setToDefaults();
1530 mConfiguration.locale = Locale.getDefault();
Dianne Hackborn813075a62011-11-14 17:45:19 -08001531 mConfigurationSeq = mConfiguration.seq = 1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001532 mProcessStats.init();
1533
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07001534 mCompatModePackages = new CompatModePackages(this, systemDir);
1535
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001536 // Add ourself to the Watchdog monitors.
1537 Watchdog.getInstance().addMonitor(this);
1538
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001539 mProcessStatsThread = new Thread("ProcessStats") {
1540 public void run() {
1541 while (true) {
1542 try {
1543 try {
1544 synchronized(this) {
1545 final long now = SystemClock.uptimeMillis();
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001546 long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001547 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001548 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001549 // + ", write delay=" + nextWriteDelay);
1550 if (nextWriteDelay < nextCpuDelay) {
1551 nextCpuDelay = nextWriteDelay;
1552 }
1553 if (nextCpuDelay > 0) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001554 mProcessStatsMutexFree.set(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001555 this.wait(nextCpuDelay);
1556 }
1557 }
1558 } catch (InterruptedException e) {
1559 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001560 updateCpuStatsNow();
1561 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001562 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001563 }
1564 }
1565 }
1566 };
1567 mProcessStatsThread.start();
1568 }
1569
1570 @Override
1571 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1572 throws RemoteException {
1573 try {
1574 return super.onTransact(code, data, reply, flags);
1575 } catch (RuntimeException e) {
1576 // The activity manager only throws security exceptions, so let's
1577 // log all others.
1578 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001579 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001580 }
1581 throw e;
1582 }
1583 }
1584
1585 void updateCpuStats() {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001586 final long now = SystemClock.uptimeMillis();
1587 if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
1588 return;
1589 }
1590 if (mProcessStatsMutexFree.compareAndSet(true, false)) {
1591 synchronized (mProcessStatsThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001592 mProcessStatsThread.notify();
1593 }
1594 }
1595 }
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001596
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001597 void updateCpuStatsNow() {
1598 synchronized (mProcessStatsThread) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001599 mProcessStatsMutexFree.set(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001600 final long now = SystemClock.uptimeMillis();
1601 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001602
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001603 if (MONITOR_CPU_USAGE &&
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001604 mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
1605 mLastCpuTime.set(now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001606 haveNewCpuStats = true;
1607 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001608 //Slog.i(TAG, mProcessStats.printCurrentState());
1609 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001610 // + mProcessStats.getTotalCpuPercent() + "%");
1611
Joe Onorato8a9b2202010-02-26 18:56:32 -08001612 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001613 if ("true".equals(SystemProperties.get("events.cpu"))) {
1614 int user = mProcessStats.getLastUserTime();
1615 int system = mProcessStats.getLastSystemTime();
1616 int iowait = mProcessStats.getLastIoWaitTime();
1617 int irq = mProcessStats.getLastIrqTime();
1618 int softIrq = mProcessStats.getLastSoftIrqTime();
1619 int idle = mProcessStats.getLastIdleTime();
1620
1621 int total = user + system + iowait + irq + softIrq + idle;
1622 if (total == 0) total = 1;
1623
Doug Zongker2bec3d42009-12-04 12:52:44 -08001624 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001625 ((user+system+iowait+irq+softIrq) * 100) / total,
1626 (user * 100) / total,
1627 (system * 100) / total,
1628 (iowait * 100) / total,
1629 (irq * 100) / total,
1630 (softIrq * 100) / total);
1631 }
1632 }
1633
Amith Yamasanie43530a2009-08-21 13:11:37 -07001634 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001635 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001636 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001637 synchronized(mPidsSelfLocked) {
1638 if (haveNewCpuStats) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001639 if (mOnBattery) {
1640 int perc = bstats.startAddingCpuLocked();
1641 int totalUTime = 0;
1642 int totalSTime = 0;
Dianne Hackborn287952c2010-09-22 22:34:31 -07001643 final int N = mProcessStats.countStats();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001644 for (int i=0; i<N; i++) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001645 ProcessStats.Stats st = mProcessStats.getStats(i);
1646 if (!st.working) {
1647 continue;
1648 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001649 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001650 int otherUTime = (st.rel_utime*perc)/100;
1651 int otherSTime = (st.rel_stime*perc)/100;
1652 totalUTime += otherUTime;
1653 totalSTime += otherSTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001654 if (pr != null) {
1655 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001656 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1657 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001658 ps.addSpeedStepTimes(cpuSpeedTimes);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001659 pr.curCpuTime += (st.rel_utime+st.rel_stime) * 10;
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001660 } else {
1661 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001662 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001663 if (ps != null) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001664 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1665 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001666 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001667 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001668 }
1669 }
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001670 bstats.finishAddingCpuLocked(perc, totalUTime,
1671 totalSTime, cpuSpeedTimes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001672 }
1673 }
1674 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001675
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001676 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1677 mLastWriteTime = now;
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001678 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001679 }
1680 }
1681 }
1682 }
1683
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001684 @Override
1685 public void batteryNeedsCpuUpdate() {
1686 updateCpuStatsNow();
1687 }
1688
1689 @Override
1690 public void batteryPowerChanged(boolean onBattery) {
1691 // When plugging in, update the CPU stats first before changing
1692 // the plug state.
1693 updateCpuStatsNow();
1694 synchronized (this) {
1695 synchronized(mPidsSelfLocked) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001696 mOnBattery = DEBUG_POWER ? true : onBattery;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001697 }
1698 }
1699 }
1700
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001701 /**
1702 * Initialize the application bind args. These are passed to each
1703 * process when the bindApplication() IPC is sent to the process. They're
1704 * lazily setup to make sure the services are running when they're asked for.
1705 */
1706 private HashMap<String, IBinder> getCommonServicesLocked() {
1707 if (mAppBindArgs == null) {
1708 mAppBindArgs = new HashMap<String, IBinder>();
1709
1710 // Setup the application init args
1711 mAppBindArgs.put("package", ServiceManager.getService("package"));
1712 mAppBindArgs.put("window", ServiceManager.getService("window"));
1713 mAppBindArgs.put(Context.ALARM_SERVICE,
1714 ServiceManager.getService(Context.ALARM_SERVICE));
1715 }
1716 return mAppBindArgs;
1717 }
1718
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001719 final void setFocusedActivityLocked(ActivityRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001720 if (mFocusedActivity != r) {
1721 mFocusedActivity = r;
Dianne Hackbornee9aef02011-11-16 13:21:46 -08001722 if (r != null) {
1723 mWindowManager.setFocusedApp(r.appToken, true);
1724 }
Christopher Tate9ce685b2012-03-15 16:27:14 -07001725 applyUpdateLockStateLocked(r);
1726 }
1727 }
1728
1729 final void applyUpdateLockStateLocked(ActivityRecord r) {
1730 final boolean nextState = r != null && r.immersive;
1731 if (mUpdateLock.isHeld() != nextState) {
1732 if (DEBUG_IMMERSIVE) {
1733 Slog.d(TAG, "Applying new update lock state '" + nextState + "' for " + r);
1734 }
1735 if (nextState) {
1736 mUpdateLock.acquire();
1737 } else {
1738 mUpdateLock.release();
1739 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001740 }
1741 }
1742
Dianne Hackborn906497c2010-05-10 15:57:38 -07001743 private final void updateLruProcessInternalLocked(ProcessRecord app,
1744 boolean oomAdj, boolean updateActivityTime, int bestPos) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001745 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001746 int lrui = mLruProcesses.indexOf(app);
1747 if (lrui >= 0) mLruProcesses.remove(lrui);
1748
1749 int i = mLruProcesses.size()-1;
1750 int skipTop = 0;
1751
Dianne Hackborn906497c2010-05-10 15:57:38 -07001752 app.lruSeq = mLruSeq;
1753
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001754 // compute the new weight for this process.
1755 if (updateActivityTime) {
1756 app.lastActivityTime = SystemClock.uptimeMillis();
1757 }
1758 if (app.activities.size() > 0) {
1759 // If this process has activities, we more strongly want to keep
1760 // it around.
1761 app.lruWeight = app.lastActivityTime;
1762 } else if (app.pubProviders.size() > 0) {
1763 // If this process contains content providers, we want to keep
1764 // it a little more strongly.
Dianne Hackborn7d608422011-08-07 16:24:18 -07001765 app.lruWeight = app.lastActivityTime - ProcessList.CONTENT_APP_IDLE_OFFSET;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001766 // Also don't let it kick out the first few "real" hidden processes.
Dianne Hackborn7d608422011-08-07 16:24:18 -07001767 skipTop = ProcessList.MIN_HIDDEN_APPS;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001768 } else {
1769 // If this process doesn't have activities, we less strongly
1770 // want to keep it around, and generally want to avoid getting
1771 // in front of any very recently used activities.
Dianne Hackborn7d608422011-08-07 16:24:18 -07001772 app.lruWeight = app.lastActivityTime - ProcessList.EMPTY_APP_IDLE_OFFSET;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001773 // Also don't let it kick out the first few "real" hidden processes.
Dianne Hackborn7d608422011-08-07 16:24:18 -07001774 skipTop = ProcessList.MIN_HIDDEN_APPS;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001775 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001776
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001777 while (i >= 0) {
1778 ProcessRecord p = mLruProcesses.get(i);
1779 // If this app shouldn't be in front of the first N background
1780 // apps, then skip over that many that are currently hidden.
Dianne Hackborn7d608422011-08-07 16:24:18 -07001781 if (skipTop > 0 && p.setAdj >= ProcessList.HIDDEN_APP_MIN_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001782 skipTop--;
1783 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001784 if (p.lruWeight <= app.lruWeight || i < bestPos) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001785 mLruProcesses.add(i+1, app);
1786 break;
1787 }
1788 i--;
1789 }
1790 if (i < 0) {
1791 mLruProcesses.add(0, app);
1792 }
1793
Dianne Hackborn906497c2010-05-10 15:57:38 -07001794 // If the app is currently using a content provider or service,
1795 // bump those processes as well.
1796 if (app.connections.size() > 0) {
1797 for (ConnectionRecord cr : app.connections) {
1798 if (cr.binding != null && cr.binding.service != null
1799 && cr.binding.service.app != null
1800 && cr.binding.service.app.lruSeq != mLruSeq) {
1801 updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,
1802 updateActivityTime, i+1);
1803 }
1804 }
1805 }
1806 if (app.conProviders.size() > 0) {
1807 for (ContentProviderRecord cpr : app.conProviders.keySet()) {
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07001808 if (cpr.proc != null && cpr.proc.lruSeq != mLruSeq) {
1809 updateLruProcessInternalLocked(cpr.proc, oomAdj,
Dianne Hackborn906497c2010-05-10 15:57:38 -07001810 updateActivityTime, i+1);
1811 }
1812 }
1813 }
1814
Joe Onorato8a9b2202010-02-26 18:56:32 -08001815 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001816 if (oomAdj) {
1817 updateOomAdjLocked();
1818 }
1819 }
1820
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001821 final void updateLruProcessLocked(ProcessRecord app,
Dianne Hackborn906497c2010-05-10 15:57:38 -07001822 boolean oomAdj, boolean updateActivityTime) {
1823 mLruSeq++;
1824 updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
1825 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07001826
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001827 final ProcessRecord getProcessRecordLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001828 String processName, int uid) {
1829 if (uid == Process.SYSTEM_UID) {
1830 // The system gets to run in any process. If there are multiple
1831 // processes with the same uid, just pick the first (this
1832 // should never happen).
1833 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1834 processName);
1835 return procs != null ? procs.valueAt(0) : null;
1836 }
1837 ProcessRecord proc = mProcessNames.get(processName, uid);
1838 return proc;
1839 }
1840
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001841 void ensurePackageDexOpt(String packageName) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001842 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001843 try {
1844 if (pm.performDexOpt(packageName)) {
1845 mDidDexOpt = true;
1846 }
1847 } catch (RemoteException e) {
1848 }
1849 }
1850
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001851 boolean isNextTransitionForward() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001852 int transit = mWindowManager.getPendingAppTransition();
1853 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1854 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1855 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1856 }
1857
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001858 final ProcessRecord startProcessLocked(String processName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001859 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001860 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001861 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1862 // We don't have to do anything more if:
1863 // (1) There is an existing application record; and
1864 // (2) The caller doesn't think it is dead, OR there is no thread
1865 // object attached to it so we know it couldn't have crashed; and
1866 // (3) There is a pid assigned to it, so it is either starting or
1867 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001868 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001869 + " app=" + app + " knownToBeDead=" + knownToBeDead
1870 + " thread=" + (app != null ? app.thread : null)
1871 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01001872 if (app != null && app.pid > 0) {
1873 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001874 // We already have the app running, or are waiting for it to
1875 // come up (we have a pid but not yet its thread), so keep it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001876 if (DEBUG_PROCESSES) Slog.v(TAG, "App already running: " + app);
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001877 // If this is a new package in the process, add the package to the list
1878 app.addPackage(info.packageName);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001879 return app;
1880 } else {
1881 // An application record is attached to a previous process,
1882 // clean it up now.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001883 if (DEBUG_PROCESSES) Slog.v(TAG, "App died: " + app);
Dianne Hackborn130b0d22011-07-26 22:07:48 -07001884 handleAppDiedLocked(app, true, true);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001885 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001886 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01001887
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001888 String hostingNameStr = hostingName != null
1889 ? hostingName.flattenToShortString() : null;
1890
1891 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1892 // If we are in the background, then check to see if this process
1893 // is bad. If so, we will just silently fail.
1894 if (mBadProcesses.get(info.processName, info.uid) != null) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001895 if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid
1896 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001897 return null;
1898 }
1899 } else {
1900 // When the user is explicitly starting a process, then clear its
1901 // crash count so that we won't make it bad until they see at
1902 // least one crash dialog again, and make the process good again
1903 // if it had been bad.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001904 if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
1905 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001906 mProcessCrashTimes.remove(info.processName, info.uid);
1907 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001908 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001909 info.processName);
1910 mBadProcesses.remove(info.processName, info.uid);
1911 if (app != null) {
1912 app.bad = false;
1913 }
1914 }
1915 }
1916
1917 if (app == null) {
1918 app = newProcessRecordLocked(null, info, processName);
1919 mProcessNames.put(processName, info.uid, app);
1920 } else {
1921 // If this is a new package in the process, add the package to the list
1922 app.addPackage(info.packageName);
1923 }
1924
1925 // If the system is not ready yet, then hold off on starting this
1926 // process until it is.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001927 if (!mProcessesReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001928 && !isAllowedWhileBooting(info)
1929 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001930 if (!mProcessesOnHold.contains(app)) {
1931 mProcessesOnHold.add(app);
1932 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001933 if (DEBUG_PROCESSES) Slog.v(TAG, "System not ready, putting on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001934 return app;
1935 }
1936
1937 startProcessLocked(app, hostingType, hostingNameStr);
1938 return (app.pid != 0) ? app : null;
1939 }
1940
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001941 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1942 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1943 }
1944
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001945 private final void startProcessLocked(ProcessRecord app,
1946 String hostingType, String hostingNameStr) {
1947 if (app.pid > 0 && app.pid != MY_PID) {
1948 synchronized (mPidsSelfLocked) {
1949 mPidsSelfLocked.remove(app.pid);
1950 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1951 }
1952 app.pid = 0;
1953 }
1954
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001955 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
1956 "startProcessLocked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001957 mProcessesOnHold.remove(app);
1958
1959 updateCpuStats();
1960
1961 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1962 mProcDeaths[0] = 0;
1963
1964 try {
1965 int uid = app.info.uid;
1966 int[] gids = null;
1967 try {
1968 gids = mContext.getPackageManager().getPackageGids(
1969 app.info.packageName);
1970 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001971 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001972 }
1973 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1974 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1975 && mTopComponent != null
1976 && app.processName.equals(mTopComponent.getPackageName())) {
1977 uid = 0;
1978 }
1979 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1980 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1981 uid = 0;
1982 }
1983 }
1984 int debugFlags = 0;
1985 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1986 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
Elliott Hughesfa36aee2011-06-17 14:39:41 -07001987 // Also turn on CheckJNI for debuggable apps. It's quite
1988 // awkward to turn on otherwise.
1989 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001990 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08001991 // Run the app in safe mode if its manifest requests so or the
1992 // system is booted in safe mode.
1993 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
1994 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08001995 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1996 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001997 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1998 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1999 }
Elliott Hughesae07ecf2011-07-06 17:33:27 -07002000 if ("1".equals(SystemProperties.get("debug.jni.logging"))) {
2001 debugFlags |= Zygote.DEBUG_ENABLE_JNI_LOGGING;
2002 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002003 if ("1".equals(SystemProperties.get("debug.assert"))) {
2004 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
2005 }
Jeff Brown3f9dd282011-07-08 20:02:19 -07002006
2007 // Start the process. It will either succeed and return a result containing
2008 // the PID of the new process, or else throw a RuntimeException.
2009 Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
Elliott Hughese1dfcb72011-07-08 11:08:07 -07002010 app.processName, uid, uid, gids, debugFlags,
2011 app.info.targetSdkVersion, null);
Jeff Brown3f9dd282011-07-08 20:02:19 -07002012
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002013 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
2014 synchronized (bs) {
2015 if (bs.isOnBattery()) {
2016 app.batteryStats.incStartsLocked();
2017 }
2018 }
2019
Jeff Brown3f9dd282011-07-08 20:02:19 -07002020 EventLog.writeEvent(EventLogTags.AM_PROC_START, startResult.pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002021 app.processName, hostingType,
2022 hostingNameStr != null ? hostingNameStr : "");
2023
2024 if (app.persistent) {
Jeff Brown3f9dd282011-07-08 20:02:19 -07002025 Watchdog.getInstance().processStarted(app.processName, startResult.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002026 }
2027
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002028 StringBuilder buf = mStringBuilder;
2029 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002030 buf.append("Start proc ");
2031 buf.append(app.processName);
2032 buf.append(" for ");
2033 buf.append(hostingType);
2034 if (hostingNameStr != null) {
2035 buf.append(" ");
2036 buf.append(hostingNameStr);
2037 }
2038 buf.append(": pid=");
Jeff Brown3f9dd282011-07-08 20:02:19 -07002039 buf.append(startResult.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002040 buf.append(" uid=");
2041 buf.append(uid);
2042 buf.append(" gids={");
2043 if (gids != null) {
2044 for (int gi=0; gi<gids.length; gi++) {
2045 if (gi != 0) buf.append(", ");
2046 buf.append(gids[gi]);
2047
2048 }
2049 }
2050 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08002051 Slog.i(TAG, buf.toString());
Jeff Brown3f9dd282011-07-08 20:02:19 -07002052 app.pid = startResult.pid;
2053 app.usingWrapper = startResult.usingWrapper;
2054 app.removed = false;
2055 synchronized (mPidsSelfLocked) {
2056 this.mPidsSelfLocked.put(startResult.pid, app);
2057 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
2058 msg.obj = app;
2059 mHandler.sendMessageDelayed(msg, startResult.usingWrapper
2060 ? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002061 }
2062 } catch (RuntimeException e) {
2063 // XXX do better error recovery.
2064 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002065 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002066 }
2067 }
2068
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002069 void updateUsageStats(ActivityRecord resumedComponent, boolean resumed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002070 if (resumed) {
2071 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
2072 } else {
2073 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
2074 }
2075 }
2076
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002077 boolean startHomeActivityLocked() {
Mike Lockwoodbc069282011-08-31 14:32:37 -04002078 if (mHeadless) {
2079 // Added because none of the other calls to ensureBootCompleted seem to fire
2080 // when running headless.
2081 ensureBootCompleted();
2082 return false;
2083 }
Mike Lockwooda0a8b242011-08-12 13:55:22 -07002084
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002085 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
2086 && mTopAction == null) {
2087 // We are running in factory test mode, but unable to find
2088 // the factory test app, so just sit around displaying the
2089 // error message and don't try to start anything.
2090 return false;
2091 }
2092 Intent intent = new Intent(
2093 mTopAction,
2094 mTopData != null ? Uri.parse(mTopData) : null);
2095 intent.setComponent(mTopComponent);
2096 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
2097 intent.addCategory(Intent.CATEGORY_HOME);
2098 }
2099 ActivityInfo aInfo =
2100 intent.resolveActivityInfo(mContext.getPackageManager(),
2101 STOCK_PM_FLAGS);
2102 if (aInfo != null) {
2103 intent.setComponent(new ComponentName(
2104 aInfo.applicationInfo.packageName, aInfo.name));
2105 // Don't do this if the home app is currently being
2106 // instrumented.
2107 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
2108 aInfo.applicationInfo.uid);
2109 if (app == null || app.instrumentationClass == null) {
2110 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002111 mMainStack.startActivityLocked(null, intent, null, null, 0, aInfo,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002112 null, null, 0, 0, 0, false, false, null);
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002113 }
2114 }
2115
2116
2117 return true;
2118 }
2119
2120 /**
2121 * Starts the "new version setup screen" if appropriate.
2122 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002123 void startSetupActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002124 // Only do this once per boot.
2125 if (mCheckedForSetup) {
2126 return;
2127 }
2128
2129 // We will show this screen if the current one is a different
2130 // version than the last one shown, and we are not running in
2131 // low-level factory test mode.
2132 final ContentResolver resolver = mContext.getContentResolver();
2133 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
2134 Settings.Secure.getInt(resolver,
2135 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
2136 mCheckedForSetup = true;
2137
2138 // See if we should be showing the platform update setup UI.
2139 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
2140 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
2141 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
2142
2143 // We don't allow third party apps to replace this.
2144 ResolveInfo ri = null;
2145 for (int i=0; ris != null && i<ris.size(); i++) {
2146 if ((ris.get(i).activityInfo.applicationInfo.flags
2147 & ApplicationInfo.FLAG_SYSTEM) != 0) {
2148 ri = ris.get(i);
2149 break;
2150 }
2151 }
2152
2153 if (ri != null) {
2154 String vers = ri.activityInfo.metaData != null
2155 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
2156 : null;
2157 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
2158 vers = ri.activityInfo.applicationInfo.metaData.getString(
2159 Intent.METADATA_SETUP_VERSION);
2160 }
2161 String lastVers = Settings.Secure.getString(
2162 resolver, Settings.Secure.LAST_SETUP_SHOWN);
2163 if (vers != null && !vers.equals(lastVers)) {
2164 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2165 intent.setComponent(new ComponentName(
2166 ri.activityInfo.packageName, ri.activityInfo.name));
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002167 mMainStack.startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002168 null, null, 0, 0, 0, false, false, null);
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002169 }
2170 }
2171 }
2172 }
2173
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002174 CompatibilityInfo compatibilityInfoForPackageLocked(ApplicationInfo ai) {
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002175 return mCompatModePackages.compatibilityInfoForPackageLocked(ai);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002176 }
2177
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002178 public int getFrontActivityScreenCompatMode() {
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002179 synchronized (this) {
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002180 return mCompatModePackages.getFrontActivityScreenCompatModeLocked();
2181 }
2182 }
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002183
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002184 public void setFrontActivityScreenCompatMode(int mode) {
2185 synchronized (this) {
2186 mCompatModePackages.setFrontActivityScreenCompatModeLocked(mode);
2187 }
2188 }
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002189
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002190 public int getPackageScreenCompatMode(String packageName) {
2191 synchronized (this) {
2192 return mCompatModePackages.getPackageScreenCompatModeLocked(packageName);
2193 }
2194 }
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002195
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002196 public void setPackageScreenCompatMode(String packageName, int mode) {
2197 synchronized (this) {
2198 mCompatModePackages.setPackageScreenCompatModeLocked(packageName, mode);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002199 }
2200 }
2201
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07002202 public boolean getPackageAskScreenCompat(String packageName) {
2203 synchronized (this) {
2204 return mCompatModePackages.getPackageAskCompatModeLocked(packageName);
2205 }
2206 }
2207
2208 public void setPackageAskScreenCompat(String packageName, boolean ask) {
2209 synchronized (this) {
2210 mCompatModePackages.setPackageAskCompatModeLocked(packageName, ask);
2211 }
2212 }
2213
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002214 void reportResumedActivityLocked(ActivityRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002215 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002216
2217 final int identHash = System.identityHashCode(r);
2218 updateUsageStats(r, true);
2219
2220 int i = mWatchers.beginBroadcast();
2221 while (i > 0) {
2222 i--;
2223 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2224 if (w != null) {
2225 try {
2226 w.activityResuming(identHash);
2227 } catch (RemoteException e) {
2228 }
2229 }
2230 }
2231 mWatchers.finishBroadcast();
2232 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002233
Jeff Sharkeya4620792011-05-20 15:29:23 -07002234 private void dispatchForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities) {
2235 int i = mProcessObservers.beginBroadcast();
2236 while (i > 0) {
2237 i--;
2238 final IProcessObserver observer = mProcessObservers.getBroadcastItem(i);
2239 if (observer != null) {
2240 try {
2241 observer.onForegroundActivitiesChanged(pid, uid, foregroundActivities);
2242 } catch (RemoteException e) {
2243 }
2244 }
2245 }
2246 mProcessObservers.finishBroadcast();
2247 }
2248
2249 private void dispatchProcessDied(int pid, int uid) {
2250 int i = mProcessObservers.beginBroadcast();
2251 while (i > 0) {
2252 i--;
2253 final IProcessObserver observer = mProcessObservers.getBroadcastItem(i);
2254 if (observer != null) {
2255 try {
2256 observer.onProcessDied(pid, uid);
2257 } catch (RemoteException e) {
2258 }
2259 }
2260 }
2261 mProcessObservers.finishBroadcast();
2262 }
2263
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002264 final void doPendingActivityLaunchesLocked(boolean doResume) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002265 final int N = mPendingActivityLaunches.size();
2266 if (N <= 0) {
2267 return;
2268 }
2269 for (int i=0; i<N; i++) {
2270 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002271 mMainStack.startActivityUncheckedLocked(pal.r, pal.sourceRecord,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002272 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
2273 doResume && i == (N-1));
2274 }
2275 mPendingActivityLaunches.clear();
2276 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002277
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002278 public final int startActivity(IApplicationThread caller,
2279 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2280 int grantedMode, IBinder resultTo,
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07002281 String resultWho, int requestCode, boolean onlyIfNeeded, boolean debug,
2282 String profileFile, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002283 return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002284 grantedUriPermissions, grantedMode, resultTo, resultWho,
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07002285 requestCode, onlyIfNeeded, debug, profileFile, profileFd, autoStopProfiler,
2286 null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002287 }
2288
2289 public final WaitResult startActivityAndWait(IApplicationThread caller,
2290 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2291 int grantedMode, IBinder resultTo,
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07002292 String resultWho, int requestCode, boolean onlyIfNeeded, boolean debug,
2293 String profileFile, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002294 WaitResult res = new WaitResult();
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002295 mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002296 grantedUriPermissions, grantedMode, resultTo, resultWho,
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07002297 requestCode, onlyIfNeeded, debug, profileFile, profileFd, autoStopProfiler,
2298 res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002299 return res;
2300 }
2301
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002302 public final int startActivityWithConfig(IApplicationThread caller,
2303 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2304 int grantedMode, IBinder resultTo,
2305 String resultWho, int requestCode, boolean onlyIfNeeded,
2306 boolean debug, Configuration config) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002307 return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002308 grantedUriPermissions, grantedMode, resultTo, resultWho,
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07002309 requestCode, onlyIfNeeded, debug, null, null, false, null, config);
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002310 }
2311
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002312 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002313 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002314 IBinder resultTo, String resultWho, int requestCode,
2315 int flagsMask, int flagsValues) {
2316 // Refuse possible leaked file descriptors
2317 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
2318 throw new IllegalArgumentException("File descriptors passed in Intent");
2319 }
2320
2321 IIntentSender sender = intent.getTarget();
2322 if (!(sender instanceof PendingIntentRecord)) {
2323 throw new IllegalArgumentException("Bad PendingIntent object");
2324 }
2325
2326 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002327
2328 synchronized (this) {
2329 // If this is coming from the currently resumed activity, it is
2330 // effectively saying that app switches are allowed at this point.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002331 if (mMainStack.mResumedActivity != null
2332 && mMainStack.mResumedActivity.info.applicationInfo.uid ==
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002333 Binder.getCallingUid()) {
2334 mAppSwitchesAllowedTime = 0;
2335 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002336 }
2337
Dianne Hackborn6c418d52011-06-29 14:05:33 -07002338 return pir.sendInner(0, fillInIntent, resolvedType, null,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002339 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
2340 }
2341
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002342 public boolean startNextMatchingActivity(IBinder callingActivity,
2343 Intent intent) {
2344 // Refuse possible leaked file descriptors
2345 if (intent != null && intent.hasFileDescriptors() == true) {
2346 throw new IllegalArgumentException("File descriptors passed in Intent");
2347 }
2348
2349 synchronized (this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07002350 ActivityRecord r = mMainStack.isInStackLocked(callingActivity);
2351 if (r == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002352 return false;
2353 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002354 if (r.app == null || r.app.thread == null) {
2355 // The caller is not running... d'oh!
2356 return false;
2357 }
2358 intent = new Intent(intent);
2359 // The caller is not allowed to change the data.
2360 intent.setDataAndType(r.intent.getData(), r.intent.getType());
2361 // And we are resetting to find the next component...
2362 intent.setComponent(null);
2363
2364 ActivityInfo aInfo = null;
2365 try {
2366 List<ResolveInfo> resolves =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002367 AppGlobals.getPackageManager().queryIntentActivities(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002368 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002369 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002370
2371 // Look for the original activity in the list...
2372 final int N = resolves != null ? resolves.size() : 0;
2373 for (int i=0; i<N; i++) {
2374 ResolveInfo rInfo = resolves.get(i);
2375 if (rInfo.activityInfo.packageName.equals(r.packageName)
2376 && rInfo.activityInfo.name.equals(r.info.name)) {
2377 // We found the current one... the next matching is
2378 // after it.
2379 i++;
2380 if (i<N) {
2381 aInfo = resolves.get(i).activityInfo;
2382 }
2383 break;
2384 }
2385 }
2386 } catch (RemoteException e) {
2387 }
2388
2389 if (aInfo == null) {
2390 // Nobody who is next!
2391 return false;
2392 }
2393
2394 intent.setComponent(new ComponentName(
2395 aInfo.applicationInfo.packageName, aInfo.name));
2396 intent.setFlags(intent.getFlags()&~(
2397 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
2398 Intent.FLAG_ACTIVITY_CLEAR_TOP|
2399 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
2400 Intent.FLAG_ACTIVITY_NEW_TASK));
2401
2402 // Okay now we need to start the new activity, replacing the
2403 // currently running activity. This is a little tricky because
2404 // we want to start the new one as if the current one is finished,
2405 // but not finish the current one first so that there is no flicker.
2406 // And thus...
2407 final boolean wasFinishing = r.finishing;
2408 r.finishing = true;
2409
2410 // Propagate reply information over to the new activity.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002411 final ActivityRecord resultTo = r.resultTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002412 final String resultWho = r.resultWho;
2413 final int requestCode = r.requestCode;
2414 r.resultTo = null;
2415 if (resultTo != null) {
2416 resultTo.removeResultsLocked(r, resultWho, requestCode);
2417 }
2418
2419 final long origId = Binder.clearCallingIdentity();
2420 // XXX we are not dealing with propagating grantedUriPermissions...
2421 // those are not yet exposed to user code, so there is no need.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002422 int res = mMainStack.startActivityLocked(r.app.thread, intent,
Dianne Hackbornbe707852011-11-11 14:32:10 -08002423 r.resolvedType, null, 0, aInfo,
2424 resultTo != null ? resultTo.appToken : null, resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002425 requestCode, -1, r.launchedFromUid, false, false, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002426 Binder.restoreCallingIdentity(origId);
2427
2428 r.finishing = wasFinishing;
2429 if (res != START_SUCCESS) {
2430 return false;
2431 }
2432 return true;
2433 }
2434 }
2435
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002436 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002437 Intent intent, String resolvedType, IBinder resultTo,
2438 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002439
2440 // This is so super not safe, that only the system (or okay root)
2441 // can do it.
2442 final int callingUid = Binder.getCallingUid();
2443 if (callingUid != 0 && callingUid != Process.myUid()) {
2444 throw new SecurityException(
2445 "startActivityInPackage only available to the system");
2446 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002447
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002448 return mMainStack.startActivityMayWait(null, uid, intent, resolvedType,
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07002449 null, 0, resultTo, resultWho, requestCode, onlyIfNeeded, false,
2450 null, null, false, null, null);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002451 }
2452
2453 public final int startActivities(IApplicationThread caller,
2454 Intent[] intents, String[] resolvedTypes, IBinder resultTo) {
2455 return mMainStack.startActivities(caller, -1, intents, resolvedTypes, resultTo);
2456 }
2457
2458 public final int startActivitiesInPackage(int uid,
2459 Intent[] intents, String[] resolvedTypes, IBinder resultTo) {
2460
2461 // This is so super not safe, that only the system (or okay root)
2462 // can do it.
2463 final int callingUid = Binder.getCallingUid();
2464 if (callingUid != 0 && callingUid != Process.myUid()) {
2465 throw new SecurityException(
2466 "startActivityInPackage only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002467 }
2468
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002469 return mMainStack.startActivities(null, uid, intents, resolvedTypes, resultTo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002470 }
2471
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002472 final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002473 int N = mRecentTasks.size();
Dianne Hackborn7c0e75e2010-12-21 19:15:40 -08002474 // Quick case: check if the top-most recent task is the same.
2475 if (N > 0 && mRecentTasks.get(0) == task) {
2476 return;
2477 }
2478 // Remove any existing entries that are the same kind of task.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002479 for (int i=0; i<N; i++) {
2480 TaskRecord tr = mRecentTasks.get(i);
2481 if ((task.affinity != null && task.affinity.equals(tr.affinity))
2482 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
2483 mRecentTasks.remove(i);
2484 i--;
2485 N--;
2486 if (task.intent == null) {
2487 // If the new recent task we are adding is not fully
2488 // specified, then replace it with the existing recent task.
2489 task = tr;
2490 }
2491 }
2492 }
2493 if (N >= MAX_RECENT_TASKS) {
2494 mRecentTasks.remove(N-1);
2495 }
2496 mRecentTasks.add(0, task);
2497 }
2498
2499 public void setRequestedOrientation(IBinder token,
2500 int requestedOrientation) {
2501 synchronized (this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07002502 ActivityRecord r = mMainStack.isInStackLocked(token);
2503 if (r == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002504 return;
2505 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002506 final long origId = Binder.clearCallingIdentity();
Dianne Hackbornbe707852011-11-11 14:32:10 -08002507 mWindowManager.setAppOrientation(r.appToken, requestedOrientation);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002508 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07002509 mConfiguration,
Dianne Hackbornbe707852011-11-11 14:32:10 -08002510 r.mayFreezeScreenLocked(r.app) ? r.appToken : null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002511 if (config != null) {
2512 r.frozenBeforeDestroy = true;
Dianne Hackborn813075a62011-11-14 17:45:19 -08002513 if (!updateConfigurationLocked(config, r, false, false)) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002514 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002515 }
2516 }
2517 Binder.restoreCallingIdentity(origId);
2518 }
2519 }
2520
2521 public int getRequestedOrientation(IBinder token) {
2522 synchronized (this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07002523 ActivityRecord r = mMainStack.isInStackLocked(token);
2524 if (r == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002525 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
2526 }
Dianne Hackbornbe707852011-11-11 14:32:10 -08002527 return mWindowManager.getAppOrientation(r.appToken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002528 }
2529 }
2530
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002531 /**
2532 * This is the internal entry point for handling Activity.finish().
2533 *
2534 * @param token The Binder token referencing the Activity we want to finish.
2535 * @param resultCode Result code, if any, from this Activity.
2536 * @param resultData Result data (Intent), if any, from this Activity.
2537 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11002538 * @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 -08002539 */
2540 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
2541 // Refuse possible leaked file descriptors
2542 if (resultData != null && resultData.hasFileDescriptors() == true) {
2543 throw new IllegalArgumentException("File descriptors passed in Intent");
2544 }
2545
2546 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002547 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002548 // Find the first activity that is not finishing.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002549 ActivityRecord next = mMainStack.topRunningActivityLocked(token, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002550 if (next != null) {
2551 // ask watcher if this is allowed
2552 boolean resumeOK = true;
2553 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002554 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002555 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002556 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002557 }
2558
2559 if (!resumeOK) {
2560 return false;
2561 }
2562 }
2563 }
2564 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002565 boolean res = mMainStack.requestFinishActivityLocked(token, resultCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002566 resultData, "app-request");
2567 Binder.restoreCallingIdentity(origId);
2568 return res;
2569 }
2570 }
2571
Dianne Hackborn860755f2010-06-03 18:47:52 -07002572 public final void finishHeavyWeightApp() {
2573 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2574 != PackageManager.PERMISSION_GRANTED) {
2575 String msg = "Permission Denial: finishHeavyWeightApp() from pid="
2576 + Binder.getCallingPid()
2577 + ", uid=" + Binder.getCallingUid()
2578 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2579 Slog.w(TAG, msg);
2580 throw new SecurityException(msg);
2581 }
2582
2583 synchronized(this) {
2584 if (mHeavyWeightProcess == null) {
2585 return;
2586 }
2587
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002588 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>(
Dianne Hackborn860755f2010-06-03 18:47:52 -07002589 mHeavyWeightProcess.activities);
2590 for (int i=0; i<activities.size(); i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002591 ActivityRecord r = activities.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002592 if (!r.finishing) {
Dianne Hackbornbe707852011-11-11 14:32:10 -08002593 int index = mMainStack.indexOfTokenLocked(r.appToken);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002594 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002595 mMainStack.finishActivityLocked(r, index, Activity.RESULT_CANCELED,
Dianne Hackborn860755f2010-06-03 18:47:52 -07002596 null, "finish-heavy");
2597 }
2598 }
2599 }
2600
2601 mHeavyWeightProcess = null;
2602 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
2603 }
2604 }
2605
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002606 public void crashApplication(int uid, int initialPid, String packageName,
2607 String message) {
2608 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2609 != PackageManager.PERMISSION_GRANTED) {
2610 String msg = "Permission Denial: crashApplication() from pid="
2611 + Binder.getCallingPid()
2612 + ", uid=" + Binder.getCallingUid()
2613 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2614 Slog.w(TAG, msg);
2615 throw new SecurityException(msg);
2616 }
2617
2618 synchronized(this) {
2619 ProcessRecord proc = null;
2620
2621 // Figure out which process to kill. We don't trust that initialPid
2622 // still has any relation to current pids, so must scan through the
2623 // list.
2624 synchronized (mPidsSelfLocked) {
2625 for (int i=0; i<mPidsSelfLocked.size(); i++) {
2626 ProcessRecord p = mPidsSelfLocked.valueAt(i);
2627 if (p.info.uid != uid) {
2628 continue;
2629 }
2630 if (p.pid == initialPid) {
2631 proc = p;
2632 break;
2633 }
2634 for (String str : p.pkgList) {
2635 if (str.equals(packageName)) {
2636 proc = p;
2637 }
2638 }
2639 }
2640 }
2641
2642 if (proc == null) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07002643 Slog.w(TAG, "crashApplication: nothing for uid=" + uid
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002644 + " initialPid=" + initialPid
2645 + " packageName=" + packageName);
2646 return;
2647 }
2648
2649 if (proc.thread != null) {
Dianne Hackborn9f531192010-08-04 17:48:03 -07002650 if (proc.pid == Process.myPid()) {
2651 Log.w(TAG, "crashApplication: trying to crash self!");
2652 return;
2653 }
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002654 long ident = Binder.clearCallingIdentity();
2655 try {
2656 proc.thread.scheduleCrash(message);
2657 } catch (RemoteException e) {
2658 }
2659 Binder.restoreCallingIdentity(ident);
2660 }
2661 }
2662 }
2663
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002664 public final void finishSubActivity(IBinder token, String resultWho,
2665 int requestCode) {
2666 synchronized(this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07002667 ActivityRecord self = mMainStack.isInStackLocked(token);
2668 if (self == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002669 return;
2670 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002671
2672 final long origId = Binder.clearCallingIdentity();
2673
2674 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002675 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2676 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002677 if (r.resultTo == self && r.requestCode == requestCode) {
2678 if ((r.resultWho == null && resultWho == null) ||
2679 (r.resultWho != null && r.resultWho.equals(resultWho))) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002680 mMainStack.finishActivityLocked(r, i,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002681 Activity.RESULT_CANCELED, null, "request-sub");
2682 }
2683 }
2684 }
2685
2686 Binder.restoreCallingIdentity(origId);
2687 }
2688 }
2689
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002690 public boolean willActivityBeVisible(IBinder token) {
2691 synchronized(this) {
2692 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002693 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2694 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackbornbe707852011-11-11 14:32:10 -08002695 if (r.appToken == token) {
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002696 return true;
2697 }
2698 if (r.fullscreen && !r.finishing) {
2699 return false;
2700 }
2701 }
2702 return true;
2703 }
2704 }
2705
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002706 public void overridePendingTransition(IBinder token, String packageName,
2707 int enterAnim, int exitAnim) {
2708 synchronized(this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07002709 ActivityRecord self = mMainStack.isInStackLocked(token);
2710 if (self == null) {
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002711 return;
2712 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002713
2714 final long origId = Binder.clearCallingIdentity();
2715
2716 if (self.state == ActivityState.RESUMED
2717 || self.state == ActivityState.PAUSING) {
2718 mWindowManager.overridePendingAppTransition(packageName,
2719 enterAnim, exitAnim);
2720 }
2721
2722 Binder.restoreCallingIdentity(origId);
2723 }
2724 }
2725
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002726 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002727 * Main function for removing an existing process from the activity manager
2728 * as a result of that process going away. Clears out all connections
2729 * to the process.
2730 */
2731 private final void handleAppDiedLocked(ProcessRecord app,
Dianne Hackborn130b0d22011-07-26 22:07:48 -07002732 boolean restarting, boolean allowRestart) {
2733 cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002734 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002735 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002736 }
2737
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07002738 if (mProfileProc == app) {
2739 clearProfilerLocked();
2740 }
2741
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002742 // Just in case...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002743 if (mMainStack.mPausingActivity != null && mMainStack.mPausingActivity.app == app) {
2744 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " +mMainStack.mPausingActivity);
2745 mMainStack.mPausingActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002746 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002747 if (mMainStack.mLastPausedActivity != null && mMainStack.mLastPausedActivity.app == app) {
2748 mMainStack.mLastPausedActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002749 }
2750
2751 // Remove this application's activities from active lists.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002752 mMainStack.removeHistoryRecordsForAppLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002753
2754 boolean atTop = true;
2755 boolean hasVisibleActivities = false;
2756
2757 // Clean out the history list.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002758 int i = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002759 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002760 TAG, "Removing app " + app + " from history with " + i + " entries");
2761 while (i > 0) {
2762 i--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002763 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002764 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002765 TAG, "Record #" + i + " " + r + ": app=" + r.app);
2766 if (r.app == app) {
2767 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Dianne Hackborn98cfebc2011-10-18 13:17:33 -07002768 if (ActivityStack.DEBUG_ADD_REMOVE) {
2769 RuntimeException here = new RuntimeException("here");
2770 here.fillInStackTrace();
2771 Slog.i(TAG, "Removing activity " + r + " from stack at " + i
2772 + ": haveState=" + r.haveState
2773 + " stateNotNeeded=" + r.stateNotNeeded
2774 + " finishing=" + r.finishing
2775 + " state=" + r.state, here);
2776 }
2777 if (!r.finishing) {
2778 Slog.w(TAG, "Force removing " + r + ": app died, no saved state");
Dianne Hackborn8bf0aa92011-11-29 13:54:43 -08002779 EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
2780 System.identityHashCode(r),
2781 r.task.taskId, r.shortComponentName,
2782 "proc died without state saved");
Dianne Hackborn98cfebc2011-10-18 13:17:33 -07002783 }
Dianne Hackborn5c607432012-02-28 14:44:19 -08002784 mMainStack.removeActivityFromHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002785
2786 } else {
2787 // We have the current state for this activity, so
2788 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002789 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002790 TAG, "Keeping entry, setting app to null");
2791 if (r.visible) {
2792 hasVisibleActivities = true;
2793 }
2794 r.app = null;
2795 r.nowVisible = false;
2796 if (!r.haveState) {
Dianne Hackborn98cfebc2011-10-18 13:17:33 -07002797 if (ActivityStack.DEBUG_SAVED_STATE) Slog.i(TAG,
2798 "App died, clearing saved state of " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002799 r.icicle = null;
2800 }
2801 }
2802
Dianne Hackbornce86ba82011-07-13 19:33:41 -07002803 r.stack.cleanUpActivityLocked(r, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002804 }
2805 atTop = false;
2806 }
2807
2808 app.activities.clear();
2809
2810 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002811 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002812 + " running instrumentation " + app.instrumentationClass);
2813 Bundle info = new Bundle();
2814 info.putString("shortMsg", "Process crashed.");
2815 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
2816 }
2817
2818 if (!restarting) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002819 if (!mMainStack.resumeTopActivityLocked(null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002820 // If there was nothing to resume, and we are not already
2821 // restarting this process, but there is a visible activity that
2822 // is hosted by the process... then make sure all visible
2823 // activities are running, taking care of restarting this
2824 // process.
2825 if (hasVisibleActivities) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002826 mMainStack.ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002827 }
2828 }
2829 }
2830 }
2831
2832 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
2833 IBinder threadBinder = thread.asBinder();
2834
2835 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002836 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2837 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002838 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
2839 return i;
2840 }
2841 }
2842 return -1;
2843 }
2844
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002845 final ProcessRecord getRecordForAppLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002846 IApplicationThread thread) {
2847 if (thread == null) {
2848 return null;
2849 }
2850
2851 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002852 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002853 }
2854
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002855 final void appDiedLocked(ProcessRecord app, int pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002856 IApplicationThread thread) {
2857
2858 mProcDeaths[0]++;
2859
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07002860 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
2861 synchronized (stats) {
2862 stats.noteProcessDiedLocked(app.info.uid, pid);
2863 }
2864
Magnus Edlund7bb25812010-02-24 15:45:06 +01002865 // Clean up already done if the process has been re-started.
2866 if (app.pid == pid && app.thread != null &&
2867 app.thread.asBinder() == thread.asBinder()) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07002868 if (!app.killedBackground) {
2869 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
2870 + ") has died.");
2871 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08002872 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002873 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002874 TAG, "Dying app: " + app + ", pid: " + pid
2875 + ", thread: " + thread.asBinder());
2876 boolean doLowMem = app.instrumentationClass == null;
Dianne Hackborn130b0d22011-07-26 22:07:48 -07002877 handleAppDiedLocked(app, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002878
2879 if (doLowMem) {
2880 // If there are no longer any background processes running,
2881 // and the app that died was not running instrumentation,
2882 // then tell everyone we are now low on memory.
2883 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002884 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2885 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn7d608422011-08-07 16:24:18 -07002886 if (rec.thread != null && rec.setAdj >= ProcessList.HIDDEN_APP_MIN_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002887 haveBg = true;
2888 break;
2889 }
2890 }
2891
2892 if (!haveBg) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002893 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002894 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002895 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2896 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07002897 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002898 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
2899 // The low memory report is overriding any current
2900 // state for a GC request. Make sure to do
Dianne Hackborn32907cf2010-06-10 17:50:20 -07002901 // heavy/important/visible/foreground processes first.
Dianne Hackborn7d608422011-08-07 16:24:18 -07002902 if (rec.setAdj <= ProcessList.HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002903 rec.lastRequestedGc = 0;
2904 } else {
2905 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002906 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002907 rec.reportLowMemory = true;
2908 rec.lastLowMemory = now;
2909 mProcessesToGc.remove(rec);
2910 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002911 }
2912 }
Dianne Hackborn04d6db32011-11-04 20:07:24 -07002913 mHandler.sendEmptyMessage(REPORT_MEM_USAGE);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002914 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002915 }
2916 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01002917 } else if (app.pid != pid) {
2918 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002919 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01002920 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08002921 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002922 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002923 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002924 + thread.asBinder());
2925 }
2926 }
2927
Dan Egnor42471dd2010-01-07 17:25:22 -08002928 /**
2929 * If a stack trace dump file is configured, dump process stack traces.
Christopher Tate6ee412d2010-05-28 12:01:56 -07002930 * @param clearTraces causes the dump file to be erased prior to the new
2931 * traces being written, if true; when false, the new traces will be
2932 * appended to any existing file content.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002933 * @param firstPids of dalvik VM processes to dump stack traces for first
2934 * @param lastPids of dalvik VM processes to dump stack traces for last
Dan Egnor42471dd2010-01-07 17:25:22 -08002935 * @return file containing stack traces, or null if no dump file is configured
2936 */
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002937 public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> firstPids,
2938 ProcessStats processStats, SparseArray<Boolean> lastPids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002939 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
2940 if (tracesPath == null || tracesPath.length() == 0) {
2941 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002942 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002943
2944 File tracesFile = new File(tracesPath);
2945 try {
2946 File tracesDir = tracesFile.getParentFile();
2947 if (!tracesDir.exists()) tracesFile.mkdirs();
2948 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
2949
Christopher Tate6ee412d2010-05-28 12:01:56 -07002950 if (clearTraces && tracesFile.exists()) tracesFile.delete();
Dan Egnor42471dd2010-01-07 17:25:22 -08002951 tracesFile.createNewFile();
2952 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
2953 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002954 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08002955 return null;
2956 }
2957
Dianne Hackborn2a29b3a2012-03-15 15:48:38 -07002958 dumpStackTraces(tracesPath, firstPids, processStats, lastPids);
2959 return tracesFile;
2960 }
2961
2962 private static void dumpStackTraces(String tracesPath, ArrayList<Integer> firstPids,
2963 ProcessStats processStats, SparseArray<Boolean> lastPids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002964 // Use a FileObserver to detect when traces finish writing.
2965 // The order of traces is considered important to maintain for legibility.
2966 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
2967 public synchronized void onEvent(int event, String path) { notify(); }
2968 };
2969
2970 try {
2971 observer.startWatching();
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002972
2973 // First collect all of the stacks of the most important pids.
Dianne Hackborn2a29b3a2012-03-15 15:48:38 -07002974 if (firstPids != null) {
2975 try {
2976 int num = firstPids.size();
2977 for (int i = 0; i < num; i++) {
2978 synchronized (observer) {
2979 Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT);
2980 observer.wait(200); // Wait for write-close, give up after 200msec
2981 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002982 }
Dianne Hackborn2a29b3a2012-03-15 15:48:38 -07002983 } catch (InterruptedException e) {
2984 Log.wtf(TAG, e);
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002985 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002986 }
2987
2988 // Next measure CPU usage.
2989 if (processStats != null) {
2990 processStats.init();
2991 System.gc();
2992 processStats.update();
2993 try {
2994 synchronized (processStats) {
2995 processStats.wait(500); // measure over 1/2 second.
2996 }
2997 } catch (InterruptedException e) {
2998 }
2999 processStats.update();
3000
3001 // We'll take the stack crawls of just the top apps using CPU.
3002 final int N = processStats.countWorkingStats();
3003 int numProcs = 0;
3004 for (int i=0; i<N && numProcs<5; i++) {
3005 ProcessStats.Stats stats = processStats.getWorkingStats(i);
3006 if (lastPids.indexOfKey(stats.pid) >= 0) {
3007 numProcs++;
3008 try {
3009 synchronized (observer) {
3010 Process.sendSignal(stats.pid, Process.SIGNAL_QUIT);
3011 observer.wait(200); // Wait for write-close, give up after 200msec
3012 }
3013 } catch (InterruptedException e) {
3014 Log.wtf(TAG, e);
3015 }
3016
3017 }
Dan Egnor42471dd2010-01-07 17:25:22 -08003018 }
3019 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003020
Dan Egnor42471dd2010-01-07 17:25:22 -08003021 } finally {
3022 observer.stopWatching();
3023 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003024 }
3025
Jeff Brown4d94a762010-09-23 11:33:28 -07003026 private final class AppNotResponding implements Runnable {
3027 private final ProcessRecord mApp;
3028 private final String mAnnotation;
3029
3030 public AppNotResponding(ProcessRecord app, String annotation) {
3031 mApp = app;
3032 mAnnotation = annotation;
3033 }
3034
3035 @Override
3036 public void run() {
3037 appNotResponding(mApp, null, null, mAnnotation);
3038 }
3039 }
3040
Dianne Hackborn2a29b3a2012-03-15 15:48:38 -07003041 final void logAppTooSlow(ProcessRecord app, long startTime, String msg) {
3042 if (IS_USER_BUILD) {
3043 return;
3044 }
3045 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
3046 if (tracesPath == null || tracesPath.length() == 0) {
3047 return;
3048 }
3049
3050 StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
3051 StrictMode.allowThreadDiskWrites();
3052 try {
3053 final File tracesFile = new File(tracesPath);
3054 final File tracesDir = tracesFile.getParentFile();
3055 final File tracesTmp = new File(tracesDir, "__tmp__");
3056 try {
3057 if (!tracesDir.exists()) tracesFile.mkdirs();
3058 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
3059
3060 if (tracesFile.exists()) {
3061 tracesTmp.delete();
3062 tracesFile.renameTo(tracesTmp);
3063 }
3064 StringBuilder sb = new StringBuilder();
3065 Time tobj = new Time();
3066 tobj.set(System.currentTimeMillis());
3067 sb.append(tobj.format("%Y-%m-%d %H:%M:%S"));
3068 sb.append(": ");
3069 TimeUtils.formatDuration(SystemClock.uptimeMillis()-startTime, sb);
3070 sb.append(" since ");
3071 sb.append(msg);
3072 FileOutputStream fos = new FileOutputStream(tracesFile);
3073 fos.write(sb.toString().getBytes());
3074 if (app == null) {
3075 fos.write("\n*** No application process!".getBytes());
3076 }
3077 fos.close();
3078 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
3079 } catch (IOException e) {
3080 Slog.w(TAG, "Unable to prepare slow app traces file: " + tracesPath, e);
3081 return;
3082 }
3083
3084 if (app != null) {
3085 ArrayList<Integer> firstPids = new ArrayList<Integer>();
3086 firstPids.add(app.pid);
3087 dumpStackTraces(tracesPath, firstPids, null, null);
3088 }
3089
3090 File lastTracesFile = null;
3091 File curTracesFile = null;
3092 for (int i=9; i>=0; i--) {
3093 String name = String.format("slow%02d.txt", i);
3094 curTracesFile = new File(tracesDir, name);
3095 if (curTracesFile.exists()) {
3096 if (lastTracesFile != null) {
3097 curTracesFile.renameTo(lastTracesFile);
3098 } else {
3099 curTracesFile.delete();
3100 }
3101 }
3102 lastTracesFile = curTracesFile;
3103 }
3104 tracesFile.renameTo(curTracesFile);
3105 if (tracesTmp.exists()) {
3106 tracesTmp.renameTo(tracesFile);
3107 }
3108 } finally {
3109 StrictMode.setThreadPolicy(oldPolicy);
3110 }
3111 }
3112
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003113 final void appNotResponding(ProcessRecord app, ActivityRecord activity,
3114 ActivityRecord parent, final String annotation) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003115 ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
3116 SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20);
3117
Dianne Hackborn287952c2010-09-22 22:34:31 -07003118 if (mController != null) {
3119 try {
3120 // 0 == continue, -1 = kill process immediately
3121 int res = mController.appEarlyNotResponding(app.processName, app.pid, annotation);
3122 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
3123 } catch (RemoteException e) {
3124 mController = null;
3125 }
3126 }
3127
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003128 long anrTime = SystemClock.uptimeMillis();
3129 if (MONITOR_CPU_USAGE) {
3130 updateCpuStatsNow();
3131 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003132
3133 synchronized (this) {
3134 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
3135 if (mShuttingDown) {
3136 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
3137 return;
3138 } else if (app.notResponding) {
3139 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
3140 return;
3141 } else if (app.crashing) {
3142 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
3143 return;
3144 }
3145
3146 // In case we come through here for the same app before completing
3147 // this one, mark as anring now so we will bail out.
3148 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08003149
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003150 // Log the ANR to the event log.
3151 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
3152 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08003153
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003154 // Dump thread traces as quickly as we can, starting with "interesting" processes.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003155 firstPids.add(app.pid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003156
3157 int parentPid = app.pid;
3158 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003159 if (parentPid != app.pid) firstPids.add(parentPid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003160
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003161 if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08003162
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003163 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
3164 ProcessRecord r = mLruProcesses.get(i);
3165 if (r != null && r.thread != null) {
3166 int pid = r.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003167 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
3168 if (r.persistent) {
3169 firstPids.add(pid);
3170 } else {
3171 lastPids.put(pid, Boolean.TRUE);
3172 }
3173 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003174 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003175 }
3176 }
3177
Dan Egnor42471dd2010-01-07 17:25:22 -08003178 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07003179 StringBuilder info = mStringBuilder;
3180 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08003181 info.append("ANR in ").append(app.processName);
3182 if (activity != null && activity.shortComponentName != null) {
3183 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07003184 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08003185 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003186 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08003187 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003188 }
Dan Egnor42471dd2010-01-07 17:25:22 -08003189 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08003190 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003191 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003192
Dianne Hackborn287952c2010-09-22 22:34:31 -07003193 final ProcessStats processStats = new ProcessStats(true);
3194
3195 File tracesFile = dumpStackTraces(true, firstPids, processStats, lastPids);
3196
Dan Egnor42471dd2010-01-07 17:25:22 -08003197 String cpuInfo = null;
3198 if (MONITOR_CPU_USAGE) {
3199 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003200 synchronized (mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003201 cpuInfo = mProcessStats.printCurrentState(anrTime);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003202 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003203 info.append(processStats.printCurrentLoad());
Dan Egnor42471dd2010-01-07 17:25:22 -08003204 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003205 }
3206
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003207 info.append(processStats.printCurrentState(anrTime));
3208
Joe Onorato8a9b2202010-02-26 18:56:32 -08003209 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08003210 if (tracesFile == null) {
3211 // There is no trace file, so dump (only) the alleged culprit's threads to the log
3212 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
3213 }
3214
Jeff Sharkeya353d262011-10-28 11:12:06 -07003215 addErrorToDropBox("anr", app, app.processName, activity, parent, annotation,
3216 cpuInfo, tracesFile, null);
Dan Egnor42471dd2010-01-07 17:25:22 -08003217
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003218 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003219 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08003220 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
3221 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003222 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08003223 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
3224 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003225 }
3226 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003227 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003228 }
3229 }
3230
Dan Egnor42471dd2010-01-07 17:25:22 -08003231 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
3232 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
3233 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003234
3235 synchronized (this) {
3236 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07003237 Slog.w(TAG, "Killing " + app + ": background ANR");
3238 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
3239 app.processName, app.setAdj, "background ANR");
3240 Process.killProcessQuiet(app.pid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003241 return;
3242 }
3243
3244 // Set the app's notResponding state, and look up the errorReportReceiver
3245 makeAppNotRespondingLocked(app,
3246 activity != null ? activity.shortComponentName : null,
3247 annotation != null ? "ANR " + annotation : "ANR",
3248 info.toString());
3249
3250 // Bring up the infamous App Not Responding dialog
3251 Message msg = Message.obtain();
3252 HashMap map = new HashMap();
3253 msg.what = SHOW_NOT_RESPONDING_MSG;
3254 msg.obj = map;
3255 map.put("app", app);
3256 if (activity != null) {
3257 map.put("activity", activity);
3258 }
3259
3260 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08003261 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003262 }
3263
Dianne Hackborn0dad3642010-09-09 21:25:35 -07003264 final void showLaunchWarningLocked(final ActivityRecord cur, final ActivityRecord next) {
3265 if (!mLaunchWarningShown) {
3266 mLaunchWarningShown = true;
3267 mHandler.post(new Runnable() {
3268 @Override
3269 public void run() {
3270 synchronized (ActivityManagerService.this) {
3271 final Dialog d = new LaunchWarningWindow(mContext, cur, next);
3272 d.show();
3273 mHandler.postDelayed(new Runnable() {
3274 @Override
3275 public void run() {
3276 synchronized (ActivityManagerService.this) {
3277 d.dismiss();
3278 mLaunchWarningShown = false;
3279 }
3280 }
3281 }, 4000);
3282 }
3283 }
3284 });
3285 }
3286 }
3287
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003288 public boolean clearApplicationUserData(final String packageName,
3289 final IPackageDataObserver observer) {
3290 int uid = Binder.getCallingUid();
3291 int pid = Binder.getCallingPid();
3292 long callingId = Binder.clearCallingIdentity();
3293 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003294 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003295 int pkgUid = -1;
3296 synchronized(this) {
3297 try {
3298 pkgUid = pm.getPackageUid(packageName);
3299 } catch (RemoteException e) {
3300 }
3301 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003302 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003303 return false;
3304 }
3305 if (uid == pkgUid || checkComponentPermission(
3306 android.Manifest.permission.CLEAR_APP_USER_DATA,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08003307 pid, uid, -1, true)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003308 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003309 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003310 } else {
3311 throw new SecurityException(pid+" does not have permission:"+
3312 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
3313 "for process:"+packageName);
3314 }
3315 }
3316
3317 try {
3318 //clear application user data
3319 pm.clearApplicationUserData(packageName, observer);
3320 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
3321 Uri.fromParts("package", packageName, null));
3322 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003323 broadcastIntentInPackage("android", Process.SYSTEM_UID, intent,
3324 null, null, 0, null, null, null, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003325 } catch (RemoteException e) {
3326 }
3327 } finally {
3328 Binder.restoreCallingIdentity(callingId);
3329 }
3330 return true;
3331 }
3332
Dianne Hackborn03abb812010-01-04 18:43:19 -08003333 public void killBackgroundProcesses(final String packageName) {
3334 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
3335 != PackageManager.PERMISSION_GRANTED &&
3336 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
3337 != PackageManager.PERMISSION_GRANTED) {
3338 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003339 + Binder.getCallingPid()
3340 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08003341 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003342 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003343 throw new SecurityException(msg);
3344 }
3345
3346 long callingId = Binder.clearCallingIdentity();
3347 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003348 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003349 int pkgUid = -1;
3350 synchronized(this) {
3351 try {
3352 pkgUid = pm.getPackageUid(packageName);
3353 } catch (RemoteException e) {
3354 }
3355 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003356 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003357 return;
3358 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003359 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08003360 ProcessList.SERVICE_ADJ, false, true, true, false, "kill background");
3361 }
3362 } finally {
3363 Binder.restoreCallingIdentity(callingId);
3364 }
3365 }
3366
3367 public void killAllBackgroundProcesses() {
3368 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
3369 != PackageManager.PERMISSION_GRANTED) {
3370 String msg = "Permission Denial: killAllBackgroundProcesses() from pid="
3371 + Binder.getCallingPid()
3372 + ", uid=" + Binder.getCallingUid()
3373 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
3374 Slog.w(TAG, msg);
3375 throw new SecurityException(msg);
3376 }
3377
3378 long callingId = Binder.clearCallingIdentity();
3379 try {
3380 synchronized(this) {
3381 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
3382 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
3383 final int NA = apps.size();
3384 for (int ia=0; ia<NA; ia++) {
3385 ProcessRecord app = apps.valueAt(ia);
3386 if (app.persistent) {
3387 // we don't kill persistent processes
3388 continue;
3389 }
3390 if (app.removed) {
3391 procs.add(app);
3392 } else if (app.setAdj >= ProcessList.HIDDEN_APP_MIN_ADJ) {
3393 app.removed = true;
3394 procs.add(app);
3395 }
3396 }
3397 }
3398
3399 int N = procs.size();
3400 for (int i=0; i<N; i++) {
3401 removeProcessLocked(procs.get(i), false, true, "kill all background");
3402 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003403 }
3404 } finally {
3405 Binder.restoreCallingIdentity(callingId);
3406 }
3407 }
3408
3409 public void forceStopPackage(final String packageName) {
3410 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
3411 != PackageManager.PERMISSION_GRANTED) {
3412 String msg = "Permission Denial: forceStopPackage() from pid="
3413 + Binder.getCallingPid()
3414 + ", uid=" + Binder.getCallingUid()
3415 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003416 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003417 throw new SecurityException(msg);
3418 }
3419
3420 long callingId = Binder.clearCallingIdentity();
3421 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003422 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn03abb812010-01-04 18:43:19 -08003423 int pkgUid = -1;
3424 synchronized(this) {
3425 try {
3426 pkgUid = pm.getPackageUid(packageName);
3427 } catch (RemoteException e) {
3428 }
3429 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003430 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003431 return;
3432 }
3433 forceStopPackageLocked(packageName, pkgUid);
Dianne Hackborne7f97212011-02-24 14:40:20 -08003434 try {
3435 pm.setPackageStoppedState(packageName, true);
3436 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08003437 } catch (IllegalArgumentException e) {
3438 Slog.w(TAG, "Failed trying to unstop package "
3439 + packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08003440 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003441 }
3442 } finally {
3443 Binder.restoreCallingIdentity(callingId);
3444 }
3445 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003446
3447 /*
3448 * The pkg name and uid have to be specified.
3449 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
3450 */
3451 public void killApplicationWithUid(String pkg, int uid) {
3452 if (pkg == null) {
3453 return;
3454 }
3455 // Make sure the uid is valid.
3456 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003457 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003458 return;
3459 }
3460 int callerUid = Binder.getCallingUid();
3461 // Only the system server can kill an application
3462 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07003463 // Post an aysnc message to kill the application
3464 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
3465 msg.arg1 = uid;
3466 msg.arg2 = 0;
3467 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07003468 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003469 } else {
3470 throw new SecurityException(callerUid + " cannot kill pkg: " +
3471 pkg);
3472 }
3473 }
3474
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003475 public void closeSystemDialogs(String reason) {
3476 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003477 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003478 if (reason != null) {
3479 intent.putExtra("reason", reason);
3480 }
3481
3482 final int uid = Binder.getCallingUid();
3483 final long origId = Binder.clearCallingIdentity();
3484 synchronized (this) {
3485 int i = mWatchers.beginBroadcast();
3486 while (i > 0) {
3487 i--;
3488 IActivityWatcher w = mWatchers.getBroadcastItem(i);
3489 if (w != null) {
3490 try {
3491 w.closingSystemDialogs(reason);
3492 } catch (RemoteException e) {
3493 }
3494 }
3495 }
3496 mWatchers.finishBroadcast();
3497
Dianne Hackbornffa42482009-09-23 22:20:11 -07003498 mWindowManager.closeSystemDialogs(reason);
3499
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003500 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3501 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackbornffa42482009-09-23 22:20:11 -07003502 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003503 r.stack.finishActivityLocked(r, i,
Dianne Hackbornffa42482009-09-23 22:20:11 -07003504 Activity.RESULT_CANCELED, null, "close-sys");
3505 }
3506 }
3507
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003508 broadcastIntentLocked(null, null, intent, null,
3509 null, 0, null, null, null, false, false, -1, uid);
3510 }
3511 Binder.restoreCallingIdentity(origId);
3512 }
3513
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003514 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003515 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003516 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
3517 for (int i=pids.length-1; i>=0; i--) {
3518 infos[i] = new Debug.MemoryInfo();
3519 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003520 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003521 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003522 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07003523
Dianne Hackbornb437e092011-08-05 17:50:29 -07003524 public long[] getProcessPss(int[] pids) throws RemoteException {
3525 long[] pss = new long[pids.length];
3526 for (int i=pids.length-1; i>=0; i--) {
3527 pss[i] = Debug.getPss(pids[i]);
3528 }
3529 return pss;
3530 }
3531
Christopher Tate5e1ab332009-09-01 20:32:49 -07003532 public void killApplicationProcess(String processName, int uid) {
3533 if (processName == null) {
3534 return;
3535 }
3536
3537 int callerUid = Binder.getCallingUid();
3538 // Only the system server can kill an application
3539 if (callerUid == Process.SYSTEM_UID) {
3540 synchronized (this) {
3541 ProcessRecord app = getProcessRecordLocked(processName, uid);
Christopher Tate4a627c72011-04-01 14:43:32 -07003542 if (app != null && app.thread != null) {
Christopher Tate5e1ab332009-09-01 20:32:49 -07003543 try {
3544 app.thread.scheduleSuicide();
3545 } catch (RemoteException e) {
3546 // If the other end already died, then our work here is done.
3547 }
3548 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003549 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07003550 + processName + " / " + uid);
3551 }
3552 }
3553 } else {
3554 throw new SecurityException(callerUid + " cannot kill app process: " +
3555 processName);
3556 }
3557 }
3558
Dianne Hackborn03abb812010-01-04 18:43:19 -08003559 private void forceStopPackageLocked(final String packageName, int uid) {
Christopher Tate3dacd842011-08-19 14:56:15 -07003560 forceStopPackageLocked(packageName, uid, false, false, true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003561 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
3562 Uri.fromParts("package", packageName, null));
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003563 if (!mProcessesReady) {
3564 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
3565 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003566 intent.putExtra(Intent.EXTRA_UID, uid);
3567 broadcastIntentLocked(null, null, intent,
3568 null, null, 0, null, null, null,
3569 false, false, MY_PID, Process.SYSTEM_UID);
3570 }
3571
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003572 private final boolean killPackageProcessesLocked(String packageName, int uid,
Christopher Tate3dacd842011-08-19 14:56:15 -07003573 int minOomAdj, boolean callerWillRestart, boolean allowRestart, boolean doit,
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08003574 boolean evenPersistent, String reason) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003575 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003576
Dianne Hackborn03abb812010-01-04 18:43:19 -08003577 // Remove all processes this package may have touched: all with the
3578 // same UID (except for the system or root user), and all whose name
3579 // matches the package name.
3580 final String procNamePrefix = packageName + ":";
3581 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
3582 final int NA = apps.size();
3583 for (int ia=0; ia<NA; ia++) {
3584 ProcessRecord app = apps.valueAt(ia);
Christopher Tate3dacd842011-08-19 14:56:15 -07003585 if (app.persistent && !evenPersistent) {
Christopher Tate064d8422011-07-26 15:38:07 -07003586 // we don't kill persistent processes
3587 continue;
3588 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003589 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003590 if (doit) {
3591 procs.add(app);
3592 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003593 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
3594 || app.processName.equals(packageName)
3595 || app.processName.startsWith(procNamePrefix)) {
3596 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003597 if (!doit) {
3598 return true;
3599 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003600 app.removed = true;
3601 procs.add(app);
3602 }
3603 }
3604 }
3605 }
3606
3607 int N = procs.size();
3608 for (int i=0; i<N; i++) {
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08003609 removeProcessLocked(procs.get(i), callerWillRestart, allowRestart, reason);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003610 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003611 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08003612 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003613
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003614 private final boolean forceStopPackageLocked(String name, int uid,
Christopher Tate3dacd842011-08-19 14:56:15 -07003615 boolean callerWillRestart, boolean purgeCache, boolean doit,
3616 boolean evenPersistent) {
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07003617 int i;
3618 int N;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003619
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003620 if (uid < 0) {
3621 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003622 uid = AppGlobals.getPackageManager().getPackageUid(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003623 } catch (RemoteException e) {
3624 }
3625 }
3626
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003627 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003628 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003629
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003630 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
3631 while (badApps.hasNext()) {
3632 SparseArray<Long> ba = badApps.next();
3633 if (ba.get(uid) != null) {
3634 badApps.remove();
3635 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003636 }
3637 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003638
3639 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08003640 callerWillRestart, false, doit, evenPersistent, "force stop");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003641
Dianne Hackborne5ba16a2011-09-09 12:35:29 -07003642 TaskRecord lastTask = null;
3643 for (i=0; i<mMainStack.mHistory.size(); i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003644 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackborne5ba16a2011-09-09 12:35:29 -07003645 final boolean samePackage = r.packageName.equals(name);
3646 if ((samePackage || r.task == lastTask)
Christopher Tate3dacd842011-08-19 14:56:15 -07003647 && (r.app == null || evenPersistent || !r.app.persistent)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003648 if (!doit) {
Dianne Hackborn80a7ac12011-09-22 18:32:52 -07003649 if (r.finishing) {
3650 // If this activity is just finishing, then it is not
3651 // interesting as far as something to stop.
3652 continue;
3653 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003654 return true;
3655 }
3656 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003657 Slog.i(TAG, " Force finishing activity " + r);
Dianne Hackborne5ba16a2011-09-09 12:35:29 -07003658 if (samePackage) {
3659 if (r.app != null) {
3660 r.app.removed = true;
3661 }
3662 r.app = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003663 }
Dianne Hackborne5ba16a2011-09-09 12:35:29 -07003664 lastTask = r.task;
3665 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
3666 null, "force-stop")) {
3667 i--;
3668 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003669 }
3670 }
3671
3672 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
3673 for (ServiceRecord service : mServices.values()) {
Christopher Tate064d8422011-07-26 15:38:07 -07003674 if (service.packageName.equals(name)
Christopher Tate3dacd842011-08-19 14:56:15 -07003675 && (service.app == null || evenPersistent || !service.app.persistent)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003676 if (!doit) {
3677 return true;
3678 }
3679 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003680 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003681 if (service.app != null) {
3682 service.app.removed = true;
3683 }
3684 service.app = null;
3685 services.add(service);
3686 }
3687 }
3688
3689 N = services.size();
3690 for (i=0; i<N; i++) {
3691 bringDownServiceLocked(services.get(i), true);
3692 }
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07003693
3694 ArrayList<ContentProviderRecord> providers = new ArrayList<ContentProviderRecord>();
3695 for (ContentProviderRecord provider : mProvidersByClass.values()) {
3696 if (provider.info.packageName.equals(name)
3697 && (provider.proc == null || evenPersistent || !provider.proc.persistent)) {
3698 if (!doit) {
3699 return true;
3700 }
3701 didSomething = true;
3702 providers.add(provider);
3703 }
3704 }
3705
3706 N = providers.size();
3707 for (i=0; i<N; i++) {
3708 removeDyingProviderLocked(null, providers.get(i));
3709 }
3710
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003711 if (doit) {
3712 if (purgeCache) {
3713 AttributeCache ac = AttributeCache.instance();
3714 if (ac != null) {
3715 ac.removePackage(name);
3716 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003717 }
Dianne Hackborn38cc8962011-10-13 11:33:55 -07003718 if (mBooted) {
3719 mMainStack.resumeTopActivityLocked(null);
3720 mMainStack.scheduleIdleLocked();
3721 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003722 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003723
3724 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003725 }
3726
Dianne Hackborn130b0d22011-07-26 22:07:48 -07003727 private final boolean removeProcessLocked(ProcessRecord app,
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08003728 boolean callerWillRestart, boolean allowRestart, String reason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003729 final String name = app.processName;
3730 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003731 if (DEBUG_PROCESSES) Slog.d(
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08003732 TAG, "Force removing proc " + app.toShortString() + " (" + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003733 + "/" + uid + ")");
3734
3735 mProcessNames.remove(name, uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003736 if (mHeavyWeightProcess == app) {
3737 mHeavyWeightProcess = null;
3738 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3739 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003740 boolean needRestart = false;
3741 if (app.pid > 0 && app.pid != MY_PID) {
3742 int pid = app.pid;
3743 synchronized (mPidsSelfLocked) {
3744 mPidsSelfLocked.remove(pid);
3745 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3746 }
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08003747 Slog.i(TAG, "Killing proc " + app.toShortString() + ": " + reason);
Dianne Hackborn130b0d22011-07-26 22:07:48 -07003748 handleAppDiedLocked(app, true, allowRestart);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003749 mLruProcesses.remove(app);
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08003750 Process.killProcessQuiet(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003751
3752 if (app.persistent) {
3753 if (!callerWillRestart) {
3754 addAppLocked(app.info);
3755 } else {
3756 needRestart = true;
3757 }
3758 }
3759 } else {
3760 mRemovedProcesses.add(app);
3761 }
3762
3763 return needRestart;
3764 }
3765
3766 private final void processStartTimedOutLocked(ProcessRecord app) {
3767 final int pid = app.pid;
3768 boolean gone = false;
3769 synchronized (mPidsSelfLocked) {
3770 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
3771 if (knownApp != null && knownApp.thread == null) {
3772 mPidsSelfLocked.remove(pid);
3773 gone = true;
3774 }
3775 }
3776
3777 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003778 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003779 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003780 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003781 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003782 if (mHeavyWeightProcess == app) {
3783 mHeavyWeightProcess = null;
3784 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3785 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003786 // Take care of any launching providers waiting for this process.
3787 checkAppInLaunchingProvidersLocked(app, true);
3788 // Take care of any services that are waiting for the process.
3789 for (int i=0; i<mPendingServices.size(); i++) {
3790 ServiceRecord sr = mPendingServices.get(i);
3791 if (app.info.uid == sr.appInfo.uid
3792 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003793 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003794 mPendingServices.remove(i);
3795 i--;
3796 bringDownServiceLocked(sr, true);
3797 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003798 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07003799 EventLog.writeEvent(EventLogTags.AM_KILL, pid,
3800 app.processName, app.setAdj, "start timeout");
3801 Process.killProcessQuiet(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07003802 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003803 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07003804 try {
3805 IBackupManager bm = IBackupManager.Stub.asInterface(
3806 ServiceManager.getService(Context.BACKUP_SERVICE));
3807 bm.agentDisconnected(app.info.packageName);
3808 } catch (RemoteException e) {
3809 // Can't happen; the backup manager is local
3810 }
3811 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003812 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003813 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003814 mPendingBroadcast.state = BroadcastRecord.IDLE;
3815 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003816 mPendingBroadcast = null;
3817 scheduleBroadcastsLocked();
3818 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003819 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003820 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003821 }
3822 }
3823
3824 private final boolean attachApplicationLocked(IApplicationThread thread,
3825 int pid) {
3826
3827 // Find the application record that is being attached... either via
3828 // the pid if we are running in multiple processes, or just pull the
3829 // next app record if we are emulating process with anonymous threads.
3830 ProcessRecord app;
3831 if (pid != MY_PID && pid >= 0) {
3832 synchronized (mPidsSelfLocked) {
3833 app = mPidsSelfLocked.get(pid);
3834 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003835 } else {
3836 app = null;
3837 }
3838
3839 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003840 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003841 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003842 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003843 if (pid > 0 && pid != MY_PID) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07003844 Process.killProcessQuiet(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003845 } else {
3846 try {
3847 thread.scheduleExit();
3848 } catch (Exception e) {
3849 // Ignore exceptions.
3850 }
3851 }
3852 return false;
3853 }
3854
3855 // If this application record is still attached to a previous
3856 // process, clean it up now.
3857 if (app.thread != null) {
Dianne Hackborn130b0d22011-07-26 22:07:48 -07003858 handleAppDiedLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003859 }
3860
3861 // Tell the process all about itself.
3862
Joe Onorato8a9b2202010-02-26 18:56:32 -08003863 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003864 TAG, "Binding process pid " + pid + " to record " + app);
3865
3866 String processName = app.processName;
3867 try {
Dianne Hackborn1b64e0d2011-07-17 15:23:59 -07003868 AppDeathRecipient adr = new AppDeathRecipient(
3869 app, pid, thread);
3870 thread.asBinder().linkToDeath(adr, 0);
3871 app.deathRecipient = adr;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003872 } catch (RemoteException e) {
3873 app.resetPackageList();
3874 startProcessLocked(app, "link fail", processName);
3875 return false;
3876 }
3877
Doug Zongker2bec3d42009-12-04 12:52:44 -08003878 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003879
3880 app.thread = thread;
3881 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08003882 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
3883 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003884 app.forcingToForeground = null;
3885 app.foregroundServices = false;
Dianne Hackbornf0754f5b2011-07-21 16:02:07 -07003886 app.hasShownUi = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003887 app.debugging = false;
3888
3889 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3890
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003891 boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003892 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003893
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003894 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003895 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003896 }
3897
Joe Onorato8a9b2202010-02-26 18:56:32 -08003898 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003899 TAG, "New app record " + app
3900 + " thread=" + thread.asBinder() + " pid=" + pid);
3901 try {
3902 int testMode = IApplicationThread.DEBUG_OFF;
3903 if (mDebugApp != null && mDebugApp.equals(processName)) {
3904 testMode = mWaitForDebugger
3905 ? IApplicationThread.DEBUG_WAIT
3906 : IApplicationThread.DEBUG_ON;
3907 app.debugging = true;
3908 if (mDebugTransient) {
3909 mDebugApp = mOrigDebugApp;
3910 mWaitForDebugger = mOrigWaitForDebugger;
3911 }
3912 }
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07003913 String profileFile = app.instrumentationProfileFile;
3914 ParcelFileDescriptor profileFd = null;
3915 boolean profileAutoStop = false;
3916 if (mProfileApp != null && mProfileApp.equals(processName)) {
3917 mProfileProc = app;
3918 profileFile = mProfileFile;
3919 profileFd = mProfileFd;
3920 profileAutoStop = mAutoStopProfiler;
3921 }
3922
Christopher Tate181fafa2009-05-14 11:12:14 -07003923 // If the app is being launched for restore or full backup, set it up specially
3924 boolean isRestrictedBackupMode = false;
3925 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
3926 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
Christopher Tate75a99702011-05-18 16:28:19 -07003927 || (mBackupTarget.backupMode == BackupRecord.RESTORE_FULL)
Christopher Tate181fafa2009-05-14 11:12:14 -07003928 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
3929 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003930
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07003931 ensurePackageDexOpt(app.instrumentationInfo != null
3932 ? app.instrumentationInfo.packageName
3933 : app.info.packageName);
3934 if (app.instrumentationClass != null) {
3935 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003936 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003937 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003938 + processName + " with config " + mConfiguration);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04003939 ApplicationInfo appInfo = app.instrumentationInfo != null
3940 ? app.instrumentationInfo : app.info;
Dianne Hackborn8ea5e1d2011-05-27 16:45:31 -07003941 app.compat = compatibilityInfoForPackageLocked(appInfo);
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07003942 if (profileFd != null) {
3943 profileFd = profileFd.dup();
3944 }
Dianne Hackborne2515ee2011-04-27 18:52:56 -04003945 thread.bindApplication(processName, appInfo, providers,
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07003946 app.instrumentationClass, profileFile, profileFd, profileAutoStop,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003947 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn5d927c22011-09-02 12:22:18 -07003948 isRestrictedBackupMode || !normalMode, app.persistent,
Dianne Hackborn813075a62011-11-14 17:45:19 -08003949 new Configuration(mConfiguration), app.compat, getCommonServicesLocked(),
Svetoslav Ganov54d068e2011-03-02 12:58:40 -08003950 mCoreSettingsObserver.getCoreSettingsLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003951 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003952 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003953 } catch (Exception e) {
3954 // todo: Yikes! What should we do? For now we will try to
3955 // start another process, but that could easily get us in
3956 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08003957 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003958
3959 app.resetPackageList();
Dianne Hackborn1b64e0d2011-07-17 15:23:59 -07003960 app.unlinkDeathRecipient();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003961 startProcessLocked(app, "bind fail", processName);
3962 return false;
3963 }
3964
3965 // Remove this record from the list of starting applications.
3966 mPersistentStartingProcesses.remove(app);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003967 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
3968 "Attach application locked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003969 mProcessesOnHold.remove(app);
3970
3971 boolean badApp = false;
3972 boolean didSomething = false;
3973
3974 // See if the top visible activity is waiting to run in this process...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003975 ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07003976 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003977 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
3978 && processName.equals(hr.processName)) {
3979 try {
Mike Lockwooda0a8b242011-08-12 13:55:22 -07003980 if (mHeadless) {
3981 Slog.e(TAG, "Starting activities not supported on headless device: " + hr);
3982 } else if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003983 didSomething = true;
3984 }
3985 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003986 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003987 + hr.intent.getComponent().flattenToShortString(), e);
3988 badApp = true;
3989 }
3990 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003991 mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003992 }
3993 }
3994
3995 // Find any services that should be running in this process...
3996 if (!badApp && mPendingServices.size() > 0) {
3997 ServiceRecord sr = null;
3998 try {
3999 for (int i=0; i<mPendingServices.size(); i++) {
4000 sr = mPendingServices.get(i);
4001 if (app.info.uid != sr.appInfo.uid
4002 || !processName.equals(sr.processName)) {
4003 continue;
4004 }
4005
4006 mPendingServices.remove(i);
4007 i--;
4008 realStartServiceLocked(sr, app);
4009 didSomething = true;
4010 }
4011 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004012 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004013 + sr.shortName, e);
4014 badApp = true;
4015 }
4016 }
4017
4018 // Check if the next broadcast receiver is in this process...
4019 BroadcastRecord br = mPendingBroadcast;
4020 if (!badApp && br != null && br.curApp == app) {
4021 try {
4022 mPendingBroadcast = null;
4023 processCurBroadcastLocked(br, app);
4024 didSomething = true;
4025 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004026 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004027 + br.curComponent.flattenToShortString(), e);
4028 badApp = true;
Jeff Brown4d94a762010-09-23 11:33:28 -07004029 logBroadcastReceiverDiscardLocked(br);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004030 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
4031 br.resultExtras, br.resultAbort, true);
4032 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01004033 // We need to reset the state if we fails to start the receiver.
4034 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004035 }
4036 }
4037
Christopher Tate181fafa2009-05-14 11:12:14 -07004038 // Check whether the next backup agent is in this process...
4039 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004040 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07004041 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07004042 try {
Dianne Hackborne2515ee2011-04-27 18:52:56 -04004043 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo,
4044 compatibilityInfoForPackageLocked(mBackupTarget.appInfo),
4045 mBackupTarget.backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -07004046 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004047 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07004048 e.printStackTrace();
4049 }
4050 }
4051
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004052 if (badApp) {
4053 // todo: Also need to kill application to deal with all
4054 // kinds of exceptions.
Dianne Hackborn130b0d22011-07-26 22:07:48 -07004055 handleAppDiedLocked(app, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004056 return false;
4057 }
4058
4059 if (!didSomething) {
4060 updateOomAdjLocked();
4061 }
4062
4063 return true;
4064 }
4065
4066 public final void attachApplication(IApplicationThread thread) {
4067 synchronized (this) {
4068 int callingPid = Binder.getCallingPid();
4069 final long origId = Binder.clearCallingIdentity();
4070 attachApplicationLocked(thread, callingPid);
4071 Binder.restoreCallingIdentity(origId);
4072 }
4073 }
4074
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07004075 public final void activityIdle(IBinder token, Configuration config, boolean stopProfiling) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004076 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07004077 ActivityRecord r = mMainStack.activityIdleInternal(token, false, config);
4078 if (stopProfiling) {
4079 synchronized (this) {
4080 if (mProfileProc == r.app) {
4081 if (mProfileFd != null) {
4082 try {
4083 mProfileFd.close();
4084 } catch (IOException e) {
4085 }
4086 clearProfilerLocked();
4087 }
4088 }
4089 }
4090 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004091 Binder.restoreCallingIdentity(origId);
4092 }
4093
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004094 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08004095 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07004096 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004097 mWindowManager.enableScreenAfterBoot();
4098 }
4099
Dianne Hackborn661cd522011-08-22 00:26:20 -07004100 public void showBootMessage(final CharSequence msg, final boolean always) {
4101 mWindowManager.showBootMessage(msg, always);
4102 }
4103
Dianne Hackborn90c52de2011-09-23 12:57:44 -07004104 public void dismissKeyguardOnNextActivity() {
4105 synchronized (this) {
4106 mMainStack.dismissKeyguardOnNextActivityLocked();
4107 }
4108 }
4109
Dianne Hackborn9acc0302009-08-25 00:27:12 -07004110 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004111 IntentFilter pkgFilter = new IntentFilter();
4112 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
4113 pkgFilter.addDataScheme("package");
4114 mContext.registerReceiver(new BroadcastReceiver() {
4115 @Override
4116 public void onReceive(Context context, Intent intent) {
4117 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
4118 if (pkgs != null) {
4119 for (String pkg : pkgs) {
Vairavan Srinivasan61f07652010-07-22 13:36:40 -07004120 synchronized (ActivityManagerService.this) {
Christopher Tate3dacd842011-08-19 14:56:15 -07004121 if (forceStopPackageLocked(pkg, -1, false, false, false, false)) {
Vairavan Srinivasan61f07652010-07-22 13:36:40 -07004122 setResultCode(Activity.RESULT_OK);
4123 return;
4124 }
4125 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004126 }
4127 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07004128 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004129 }, pkgFilter);
4130
4131 synchronized (this) {
4132 // Ensure that any processes we had put on hold are now started
4133 // up.
4134 final int NP = mProcessesOnHold.size();
4135 if (NP > 0) {
4136 ArrayList<ProcessRecord> procs =
4137 new ArrayList<ProcessRecord>(mProcessesOnHold);
4138 for (int ip=0; ip<NP; ip++) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07004139 if (DEBUG_PROCESSES) Slog.v(TAG, "Starting process on hold: "
4140 + procs.get(ip));
4141 startProcessLocked(procs.get(ip), "on-hold", null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004142 }
4143 }
4144
4145 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07004146 // Start looking for apps that are abusing wake locks.
4147 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07004148 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004149 // Tell anyone interested that we are done booting!
Dianne Hackbornf4c454b2010-08-11 12:47:41 -07004150 SystemProperties.set("sys.boot_completed", "1");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07004151 broadcastIntentLocked(null, null,
4152 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
4153 null, null, 0, null, null,
4154 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
4155 false, false, MY_PID, Process.SYSTEM_UID);
4156 }
4157 }
4158 }
4159
4160 final void ensureBootCompleted() {
4161 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004162 boolean enableScreen;
4163 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07004164 booting = mBooting;
4165 mBooting = false;
Mike Lockwoodd070dca2011-09-13 16:28:22 -04004166 enableScreen = !mBooted;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004167 mBooted = true;
4168 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07004169
4170 if (booting) {
4171 finishBooting();
4172 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004173
4174 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004175 enableScreenAfterBoot();
4176 }
4177 }
4178
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08004179 public final void activityPaused(IBinder token) {
4180 final long origId = Binder.clearCallingIdentity();
4181 mMainStack.activityPaused(token, false);
4182 Binder.restoreCallingIdentity(origId);
4183 }
4184
4185 public final void activityStopped(IBinder token, Bundle icicle, Bitmap thumbnail,
4186 CharSequence description) {
4187 if (localLOGV) Slog.v(
4188 TAG, "Activity stopped: token=" + token);
4189
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004190 // Refuse possible leaked file descriptors
4191 if (icicle != null && icicle.hasFileDescriptors()) {
4192 throw new IllegalArgumentException("File descriptors passed in Bundle");
4193 }
4194
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004195 ActivityRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004196
4197 final long origId = Binder.clearCallingIdentity();
4198
4199 synchronized (this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004200 r = mMainStack.isInStackLocked(token);
4201 if (r != null) {
4202 r.stack.activityStoppedLocked(r, icicle, thumbnail, description);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004203 }
4204 }
4205
4206 if (r != null) {
4207 sendPendingThumbnail(r, null, null, null, false);
4208 }
4209
4210 trimApplications();
4211
4212 Binder.restoreCallingIdentity(origId);
4213 }
4214
4215 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004216 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004217 mMainStack.activityDestroyed(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004218 }
4219
4220 public String getCallingPackage(IBinder token) {
4221 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004222 ActivityRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07004223 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004224 }
4225 }
4226
4227 public ComponentName getCallingActivity(IBinder token) {
4228 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004229 ActivityRecord r = getCallingRecordLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004230 return r != null ? r.intent.getComponent() : null;
4231 }
4232 }
4233
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004234 private ActivityRecord getCallingRecordLocked(IBinder token) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004235 ActivityRecord r = mMainStack.isInStackLocked(token);
4236 if (r == null) {
4237 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004238 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004239 return r.resultTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004240 }
4241
4242 public ComponentName getActivityClassForToken(IBinder token) {
4243 synchronized(this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004244 ActivityRecord r = mMainStack.isInStackLocked(token);
4245 if (r == null) {
4246 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004247 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004248 return r.intent.getComponent();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004249 }
4250 }
4251
4252 public String getPackageForToken(IBinder token) {
4253 synchronized(this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004254 ActivityRecord r = mMainStack.isInStackLocked(token);
4255 if (r == null) {
4256 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004257 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004258 return r.packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004259 }
4260 }
4261
4262 public IIntentSender getIntentSender(int type,
4263 String packageName, IBinder token, String resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004264 int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004265 // Refuse possible leaked file descriptors
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004266 if (intents != null) {
4267 if (intents.length < 1) {
4268 throw new IllegalArgumentException("Intents array length must be >= 1");
4269 }
4270 for (int i=0; i<intents.length; i++) {
4271 Intent intent = intents[i];
Dianne Hackborn52b0ce02011-04-14 13:09:32 -07004272 if (intent != null) {
4273 if (intent.hasFileDescriptors()) {
4274 throw new IllegalArgumentException("File descriptors passed in Intent");
4275 }
4276 if (type == INTENT_SENDER_BROADCAST &&
4277 (intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
4278 throw new IllegalArgumentException(
4279 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
4280 }
4281 intents[i] = new Intent(intent);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004282 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004283 }
4284 if (resolvedTypes != null && resolvedTypes.length != intents.length) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07004285 throw new IllegalArgumentException(
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004286 "Intent array length does not match resolvedTypes length");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07004287 }
4288 }
4289
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004290 synchronized(this) {
4291 int callingUid = Binder.getCallingUid();
4292 try {
Jeff Brown10e89712011-07-08 18:52:57 -07004293 if (callingUid != 0 && callingUid != Process.SYSTEM_UID) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004294 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004295 .getPackageUid(packageName);
4296 if (uid != Binder.getCallingUid()) {
4297 String msg = "Permission Denial: getIntentSender() from pid="
4298 + Binder.getCallingPid()
4299 + ", uid=" + Binder.getCallingUid()
4300 + ", (need uid=" + uid + ")"
4301 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004302 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004303 throw new SecurityException(msg);
4304 }
4305 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004306
4307 return getIntentSenderLocked(type, packageName, callingUid,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004308 token, resultWho, requestCode, intents, resolvedTypes, flags);
Dianne Hackborn860755f2010-06-03 18:47:52 -07004309
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004310 } catch (RemoteException e) {
4311 throw new SecurityException(e);
4312 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004313 }
4314 }
4315
4316 IIntentSender getIntentSenderLocked(int type,
4317 String packageName, int callingUid, IBinder token, String resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004318 int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004319 ActivityRecord activity = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004320 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004321 activity = mMainStack.isInStackLocked(token);
4322 if (activity == null) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07004323 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004324 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004325 if (activity.finishing) {
4326 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004327 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004328 }
4329
4330 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
4331 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
4332 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
4333 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
4334 |PendingIntent.FLAG_UPDATE_CURRENT);
4335
4336 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
4337 type, packageName, activity, resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004338 requestCode, intents, resolvedTypes, flags);
Dianne Hackborn860755f2010-06-03 18:47:52 -07004339 WeakReference<PendingIntentRecord> ref;
4340 ref = mIntentSenderRecords.get(key);
4341 PendingIntentRecord rec = ref != null ? ref.get() : null;
4342 if (rec != null) {
4343 if (!cancelCurrent) {
4344 if (updateCurrent) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004345 if (rec.key.requestIntent != null) {
4346 rec.key.requestIntent.replaceExtras(intents != null ? intents[0] : null);
4347 }
4348 if (intents != null) {
4349 intents[intents.length-1] = rec.key.requestIntent;
4350 rec.key.allIntents = intents;
4351 rec.key.allResolvedTypes = resolvedTypes;
4352 } else {
4353 rec.key.allIntents = null;
4354 rec.key.allResolvedTypes = null;
4355 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004356 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004357 return rec;
4358 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004359 rec.canceled = true;
4360 mIntentSenderRecords.remove(key);
4361 }
4362 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004363 return rec;
4364 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004365 rec = new PendingIntentRecord(this, key, callingUid);
4366 mIntentSenderRecords.put(key, rec.ref);
4367 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
4368 if (activity.pendingResults == null) {
4369 activity.pendingResults
4370 = new HashSet<WeakReference<PendingIntentRecord>>();
4371 }
4372 activity.pendingResults.add(rec.ref);
4373 }
4374 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004375 }
4376
4377 public void cancelIntentSender(IIntentSender sender) {
4378 if (!(sender instanceof PendingIntentRecord)) {
4379 return;
4380 }
4381 synchronized(this) {
4382 PendingIntentRecord rec = (PendingIntentRecord)sender;
4383 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004384 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004385 .getPackageUid(rec.key.packageName);
4386 if (uid != Binder.getCallingUid()) {
4387 String msg = "Permission Denial: cancelIntentSender() from pid="
4388 + Binder.getCallingPid()
4389 + ", uid=" + Binder.getCallingUid()
4390 + " is not allowed to cancel packges "
4391 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004392 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004393 throw new SecurityException(msg);
4394 }
4395 } catch (RemoteException e) {
4396 throw new SecurityException(e);
4397 }
4398 cancelIntentSenderLocked(rec, true);
4399 }
4400 }
4401
4402 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
4403 rec.canceled = true;
4404 mIntentSenderRecords.remove(rec.key);
4405 if (cleanActivity && rec.key.activity != null) {
4406 rec.key.activity.pendingResults.remove(rec.ref);
4407 }
4408 }
4409
4410 public String getPackageForIntentSender(IIntentSender pendingResult) {
4411 if (!(pendingResult instanceof PendingIntentRecord)) {
4412 return null;
4413 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07004414 try {
4415 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
4416 return res.key.packageName;
4417 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004418 }
4419 return null;
4420 }
4421
Dianne Hackborn6c418d52011-06-29 14:05:33 -07004422 public boolean isIntentSenderTargetedToPackage(IIntentSender pendingResult) {
4423 if (!(pendingResult instanceof PendingIntentRecord)) {
4424 return false;
4425 }
4426 try {
4427 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
4428 if (res.key.allIntents == null) {
4429 return false;
4430 }
4431 for (int i=0; i<res.key.allIntents.length; i++) {
4432 Intent intent = res.key.allIntents[i];
4433 if (intent.getPackage() != null && intent.getComponent() != null) {
4434 return false;
4435 }
4436 }
4437 return true;
4438 } catch (ClassCastException e) {
4439 }
4440 return false;
4441 }
4442
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004443 public void setProcessLimit(int max) {
4444 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4445 "setProcessLimit()");
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004446 synchronized (this) {
Dianne Hackborn7d608422011-08-07 16:24:18 -07004447 mProcessLimit = max < 0 ? ProcessList.MAX_HIDDEN_APPS : max;
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004448 mProcessLimitOverride = max;
4449 }
4450 trimApplications();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004451 }
4452
4453 public int getProcessLimit() {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004454 synchronized (this) {
4455 return mProcessLimitOverride;
4456 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004457 }
4458
4459 void foregroundTokenDied(ForegroundToken token) {
4460 synchronized (ActivityManagerService.this) {
4461 synchronized (mPidsSelfLocked) {
4462 ForegroundToken cur
4463 = mForegroundProcesses.get(token.pid);
4464 if (cur != token) {
4465 return;
4466 }
4467 mForegroundProcesses.remove(token.pid);
4468 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
4469 if (pr == null) {
4470 return;
4471 }
4472 pr.forcingToForeground = null;
4473 pr.foregroundServices = false;
4474 }
4475 updateOomAdjLocked();
4476 }
4477 }
4478
4479 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
4480 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4481 "setProcessForeground()");
4482 synchronized(this) {
4483 boolean changed = false;
4484
4485 synchronized (mPidsSelfLocked) {
4486 ProcessRecord pr = mPidsSelfLocked.get(pid);
4487 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004488 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004489 return;
4490 }
4491 ForegroundToken oldToken = mForegroundProcesses.get(pid);
4492 if (oldToken != null) {
4493 oldToken.token.unlinkToDeath(oldToken, 0);
4494 mForegroundProcesses.remove(pid);
4495 pr.forcingToForeground = null;
4496 changed = true;
4497 }
4498 if (isForeground && token != null) {
4499 ForegroundToken newToken = new ForegroundToken() {
4500 public void binderDied() {
4501 foregroundTokenDied(this);
4502 }
4503 };
4504 newToken.pid = pid;
4505 newToken.token = token;
4506 try {
4507 token.linkToDeath(newToken, 0);
4508 mForegroundProcesses.put(pid, newToken);
4509 pr.forcingToForeground = token;
4510 changed = true;
4511 } catch (RemoteException e) {
4512 // If the process died while doing this, we will later
4513 // do the cleanup with the process death link.
4514 }
4515 }
4516 }
4517
4518 if (changed) {
4519 updateOomAdjLocked();
4520 }
4521 }
4522 }
4523
4524 // =========================================================
4525 // PERMISSIONS
4526 // =========================================================
4527
4528 static class PermissionController extends IPermissionController.Stub {
4529 ActivityManagerService mActivityManagerService;
4530 PermissionController(ActivityManagerService activityManagerService) {
4531 mActivityManagerService = activityManagerService;
4532 }
4533
4534 public boolean checkPermission(String permission, int pid, int uid) {
4535 return mActivityManagerService.checkPermission(permission, pid,
4536 uid) == PackageManager.PERMISSION_GRANTED;
4537 }
4538 }
4539
4540 /**
4541 * This can be called with or without the global lock held.
4542 */
4543 int checkComponentPermission(String permission, int pid, int uid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004544 int owningUid, boolean exported) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004545 // We might be performing an operation on behalf of an indirect binder
4546 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
4547 // client identity accordingly before proceeding.
4548 Identity tlsIdentity = sCallerIdentity.get();
4549 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004550 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004551 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
4552 uid = tlsIdentity.uid;
4553 pid = tlsIdentity.pid;
4554 }
4555
4556 // Root, system server and our own process get to do everything.
Jeff Brown10e89712011-07-08 18:52:57 -07004557 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004558 return PackageManager.PERMISSION_GRANTED;
4559 }
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004560 // If there is a uid that owns whatever is being accessed, it has
4561 // blanket access to it regardless of the permissions it requires.
4562 if (owningUid >= 0 && uid == owningUid) {
4563 return PackageManager.PERMISSION_GRANTED;
4564 }
4565 // If the target is not exported, then nobody else can get to it.
4566 if (!exported) {
4567 Slog.w(TAG, "Permission denied: checkComponentPermission() owningUid=" + owningUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004568 return PackageManager.PERMISSION_DENIED;
4569 }
4570 if (permission == null) {
4571 return PackageManager.PERMISSION_GRANTED;
4572 }
4573 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004574 return AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004575 .checkUidPermission(permission, uid);
4576 } catch (RemoteException e) {
4577 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004578 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004579 }
4580 return PackageManager.PERMISSION_DENIED;
4581 }
4582
4583 /**
4584 * As the only public entry point for permissions checking, this method
4585 * can enforce the semantic that requesting a check on a null global
4586 * permission is automatically denied. (Internally a null permission
4587 * string is used when calling {@link #checkComponentPermission} in cases
4588 * when only uid-based security is needed.)
4589 *
4590 * This can be called with or without the global lock held.
4591 */
4592 public int checkPermission(String permission, int pid, int uid) {
4593 if (permission == null) {
4594 return PackageManager.PERMISSION_DENIED;
4595 }
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004596 return checkComponentPermission(permission, pid, uid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004597 }
4598
4599 /**
4600 * Binder IPC calls go through the public entry point.
4601 * This can be called with or without the global lock held.
4602 */
4603 int checkCallingPermission(String permission) {
4604 return checkPermission(permission,
4605 Binder.getCallingPid(),
4606 Binder.getCallingUid());
4607 }
4608
4609 /**
4610 * This can be called with or without the global lock held.
4611 */
4612 void enforceCallingPermission(String permission, String func) {
4613 if (checkCallingPermission(permission)
4614 == PackageManager.PERMISSION_GRANTED) {
4615 return;
4616 }
4617
4618 String msg = "Permission Denial: " + func + " from pid="
4619 + Binder.getCallingPid()
4620 + ", uid=" + Binder.getCallingUid()
4621 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004622 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004623 throw new SecurityException(msg);
4624 }
4625
4626 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
Dianne Hackborn48058e82010-09-27 16:53:23 -07004627 ProviderInfo pi, Uri uri, int uid, int modeFlags) {
4628 boolean readPerm = (modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0;
4629 boolean writePerm = (modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0;
4630 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4631 "checkHoldingPermissionsLocked: uri=" + uri + " uid=" + uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004632 try {
Dianne Hackborn48058e82010-09-27 16:53:23 -07004633 // Is the component private from the target uid?
4634 final boolean prv = !pi.exported && pi.applicationInfo.uid != uid;
4635
4636 // Acceptable if the there is no read permission needed from the
4637 // target or the target is holding the read permission.
4638 if (!readPerm) {
4639 if ((!prv && pi.readPermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004640 (pm.checkUidPermission(pi.readPermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004641 == PackageManager.PERMISSION_GRANTED)) {
4642 readPerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004643 }
4644 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004645
4646 // Acceptable if the there is no write permission needed from the
4647 // target or the target is holding the read permission.
4648 if (!writePerm) {
4649 if (!prv && (pi.writePermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004650 (pm.checkUidPermission(pi.writePermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004651 == PackageManager.PERMISSION_GRANTED)) {
4652 writePerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004653 }
4654 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004655
4656 // Acceptable if there is a path permission matching the URI that
4657 // the target holds the permission on.
4658 PathPermission[] pps = pi.pathPermissions;
4659 if (pps != null && (!readPerm || !writePerm)) {
4660 final String path = uri.getPath();
4661 int i = pps.length;
4662 while (i > 0 && (!readPerm || !writePerm)) {
4663 i--;
4664 PathPermission pp = pps[i];
4665 if (!readPerm) {
4666 final String pprperm = pp.getReadPermission();
4667 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking read perm for "
4668 + pprperm + " for " + pp.getPath()
4669 + ": match=" + pp.match(path)
4670 + " check=" + pm.checkUidPermission(pprperm, uid));
4671 if (pprperm != null && pp.match(path) &&
4672 (pm.checkUidPermission(pprperm, uid)
4673 == PackageManager.PERMISSION_GRANTED)) {
4674 readPerm = true;
4675 }
4676 }
4677 if (!writePerm) {
4678 final String ppwperm = pp.getWritePermission();
4679 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking write perm "
4680 + ppwperm + " for " + pp.getPath()
4681 + ": match=" + pp.match(path)
4682 + " check=" + pm.checkUidPermission(ppwperm, uid));
4683 if (ppwperm != null && pp.match(path) &&
4684 (pm.checkUidPermission(ppwperm, uid)
4685 == PackageManager.PERMISSION_GRANTED)) {
4686 writePerm = true;
4687 }
4688 }
4689 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004690 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004691 } catch (RemoteException e) {
4692 return false;
4693 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004694
4695 return readPerm && writePerm;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004696 }
4697
4698 private final boolean checkUriPermissionLocked(Uri uri, int uid,
4699 int modeFlags) {
4700 // Root gets to do everything.
Jeff Brown10e89712011-07-08 18:52:57 -07004701 if (uid == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004702 return true;
4703 }
4704 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
4705 if (perms == null) return false;
4706 UriPermission perm = perms.get(uri);
4707 if (perm == null) return false;
4708 return (modeFlags&perm.modeFlags) == modeFlags;
4709 }
4710
4711 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
4712 // Another redirected-binder-call permissions check as in
4713 // {@link checkComponentPermission}.
4714 Identity tlsIdentity = sCallerIdentity.get();
4715 if (tlsIdentity != null) {
4716 uid = tlsIdentity.uid;
4717 pid = tlsIdentity.pid;
4718 }
4719
4720 // Our own process gets to do everything.
4721 if (pid == MY_PID) {
4722 return PackageManager.PERMISSION_GRANTED;
4723 }
4724 synchronized(this) {
4725 return checkUriPermissionLocked(uri, uid, modeFlags)
4726 ? PackageManager.PERMISSION_GRANTED
4727 : PackageManager.PERMISSION_DENIED;
4728 }
4729 }
4730
Dianne Hackborn39792d22010-08-19 18:01:52 -07004731 /**
4732 * Check if the targetPkg can be granted permission to access uri by
4733 * the callingUid using the given modeFlags. Throws a security exception
4734 * if callingUid is not allowed to do this. Returns the uid of the target
4735 * if the URI permission grant should be performed; returns -1 if it is not
4736 * needed (for example targetPkg already has permission to access the URI).
4737 */
4738 int checkGrantUriPermissionLocked(int callingUid, String targetPkg,
4739 Uri uri, int modeFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004740 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4741 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4742 if (modeFlags == 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004743 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004744 }
4745
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004746 if (targetPkg != null) {
4747 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4748 "Checking grant " + targetPkg + " permission to " + uri);
4749 }
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004750
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004751 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004752
4753 // If this is not a content: uri, we can't do anything with it.
4754 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004755 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004756 "Can't grant URI permission for non-content URI: " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004757 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004758 }
4759
4760 String name = uri.getAuthority();
4761 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004762 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004763 if (cpr != null) {
4764 pi = cpr.info;
4765 } else {
4766 try {
4767 pi = pm.resolveContentProvider(name,
4768 PackageManager.GET_URI_PERMISSION_PATTERNS);
4769 } catch (RemoteException ex) {
4770 }
4771 }
4772 if (pi == null) {
Dianne Hackborn98cfebc2011-10-18 13:17:33 -07004773 Slog.w(TAG, "No content provider found for permission check: " + uri.toSafeString());
Dianne Hackborn39792d22010-08-19 18:01:52 -07004774 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004775 }
4776
4777 int targetUid;
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004778 if (targetPkg != null) {
4779 try {
4780 targetUid = pm.getPackageUid(targetPkg);
4781 if (targetUid < 0) {
4782 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4783 "Can't grant URI permission no uid for: " + targetPkg);
4784 return -1;
4785 }
4786 } catch (RemoteException ex) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004787 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004788 }
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004789 } else {
4790 targetUid = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004791 }
4792
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004793 if (targetUid >= 0) {
4794 // First... does the target actually need this permission?
4795 if (checkHoldingPermissionsLocked(pm, pi, uri, targetUid, modeFlags)) {
4796 // No need to grant the target this permission.
4797 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4798 "Target " + targetPkg + " already has full permission to " + uri);
4799 return -1;
4800 }
4801 } else {
4802 // First... there is no target package, so can anyone access it?
4803 boolean allowed = pi.exported;
4804 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4805 if (pi.readPermission != null) {
4806 allowed = false;
4807 }
4808 }
4809 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4810 if (pi.writePermission != null) {
4811 allowed = false;
4812 }
4813 }
4814 if (allowed) {
4815 return -1;
4816 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004817 }
4818
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004819 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004820 if (!pi.grantUriPermissions) {
4821 throw new SecurityException("Provider " + pi.packageName
4822 + "/" + pi.name
4823 + " does not allow granting of Uri permissions (uri "
4824 + uri + ")");
4825 }
4826 if (pi.uriPermissionPatterns != null) {
4827 final int N = pi.uriPermissionPatterns.length;
4828 boolean allowed = false;
4829 for (int i=0; i<N; i++) {
4830 if (pi.uriPermissionPatterns[i] != null
4831 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
4832 allowed = true;
4833 break;
4834 }
4835 }
4836 if (!allowed) {
4837 throw new SecurityException("Provider " + pi.packageName
4838 + "/" + pi.name
4839 + " does not allow granting of permission to path of Uri "
4840 + uri);
4841 }
4842 }
4843
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004844 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004845 // this uri?
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004846 if (callingUid != Process.myUid()) {
4847 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
4848 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4849 throw new SecurityException("Uid " + callingUid
4850 + " does not have permission to uri " + uri);
4851 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004852 }
4853 }
4854
Dianne Hackborn39792d22010-08-19 18:01:52 -07004855 return targetUid;
4856 }
4857
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004858 public int checkGrantUriPermission(int callingUid, String targetPkg,
4859 Uri uri, int modeFlags) {
4860 synchronized(this) {
4861 return checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4862 }
4863 }
4864
Dianne Hackborn39792d22010-08-19 18:01:52 -07004865 void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg,
4866 Uri uri, int modeFlags, UriPermissionOwner owner) {
4867 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4868 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4869 if (modeFlags == 0) {
4870 return;
4871 }
4872
4873 // So here we are: the caller has the assumed permission
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004874 // to the uri, and the target doesn't. Let's now give this to
4875 // the target.
4876
Joe Onorato8a9b2202010-02-26 18:56:32 -08004877 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004878 "Granting " + targetPkg + "/" + targetUid + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004879
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004880 HashMap<Uri, UriPermission> targetUris
4881 = mGrantedUriPermissions.get(targetUid);
4882 if (targetUris == null) {
4883 targetUris = new HashMap<Uri, UriPermission>();
4884 mGrantedUriPermissions.put(targetUid, targetUris);
4885 }
4886
4887 UriPermission perm = targetUris.get(uri);
4888 if (perm == null) {
4889 perm = new UriPermission(targetUid, uri);
4890 targetUris.put(uri, perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004891 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004892
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004893 perm.modeFlags |= modeFlags;
Dianne Hackborn39792d22010-08-19 18:01:52 -07004894 if (owner == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004895 perm.globalModeFlags |= modeFlags;
Vairavan Srinivasan91c12c22011-01-21 18:26:06 -08004896 } else {
4897 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4898 perm.readOwners.add(owner);
4899 owner.addReadPermission(perm);
4900 }
4901 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4902 perm.writeOwners.add(owner);
4903 owner.addWritePermission(perm);
4904 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004905 }
4906 }
4907
Dianne Hackborn39792d22010-08-19 18:01:52 -07004908 void grantUriPermissionLocked(int callingUid,
4909 String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) {
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004910 if (targetPkg == null) {
4911 throw new NullPointerException("targetPkg");
4912 }
4913
Dianne Hackborn39792d22010-08-19 18:01:52 -07004914 int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4915 if (targetUid < 0) {
4916 return;
4917 }
4918
4919 grantUriPermissionUncheckedLocked(targetUid, targetPkg, uri, modeFlags, owner);
4920 }
4921
4922 /**
4923 * Like checkGrantUriPermissionLocked, but takes an Intent.
4924 */
4925 int checkGrantUriPermissionFromIntentLocked(int callingUid,
4926 String targetPkg, Intent intent) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07004927 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004928 "Checking URI perm to " + (intent != null ? intent.getData() : null)
Dianne Hackbornb424b632010-08-18 15:59:05 -07004929 + " from " + intent + "; flags=0x"
4930 + Integer.toHexString(intent != null ? intent.getFlags() : 0));
4931
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004932 if (targetPkg == null) {
4933 throw new NullPointerException("targetPkg");
4934 }
4935
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004936 if (intent == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004937 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004938 }
4939 Uri data = intent.getData();
4940 if (data == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004941 return -1;
4942 }
4943 return checkGrantUriPermissionLocked(callingUid, targetPkg, data,
4944 intent.getFlags());
4945 }
4946
4947 /**
4948 * Like grantUriPermissionUncheckedLocked, but takes an Intent.
4949 */
4950 void grantUriPermissionUncheckedFromIntentLocked(int targetUid,
4951 String targetPkg, Intent intent, UriPermissionOwner owner) {
4952 grantUriPermissionUncheckedLocked(targetUid, targetPkg, intent.getData(),
4953 intent.getFlags(), owner);
4954 }
4955
4956 void grantUriPermissionFromIntentLocked(int callingUid,
4957 String targetPkg, Intent intent, UriPermissionOwner owner) {
4958 int targetUid = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg, intent);
4959 if (targetUid < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004960 return;
4961 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07004962
4963 grantUriPermissionUncheckedFromIntentLocked(targetUid, targetPkg, intent, owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004964 }
4965
4966 public void grantUriPermission(IApplicationThread caller, String targetPkg,
4967 Uri uri, int modeFlags) {
4968 synchronized(this) {
4969 final ProcessRecord r = getRecordForAppLocked(caller);
4970 if (r == null) {
4971 throw new SecurityException("Unable to find app for caller "
4972 + caller
4973 + " when granting permission to uri " + uri);
4974 }
4975 if (targetPkg == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004976 throw new IllegalArgumentException("null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004977 }
4978 if (uri == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004979 throw new IllegalArgumentException("null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004980 }
4981
4982 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
4983 null);
4984 }
4985 }
4986
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004987 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004988 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
4989 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
4990 HashMap<Uri, UriPermission> perms
4991 = mGrantedUriPermissions.get(perm.uid);
4992 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004993 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004994 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004995 perms.remove(perm.uri);
4996 if (perms.size() == 0) {
4997 mGrantedUriPermissions.remove(perm.uid);
4998 }
4999 }
5000 }
5001 }
5002
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005003 private void revokeUriPermissionLocked(int callingUid, Uri uri,
5004 int modeFlags) {
5005 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
5006 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
5007 if (modeFlags == 0) {
5008 return;
5009 }
5010
Joe Onorato8a9b2202010-02-26 18:56:32 -08005011 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08005012 "Revoking all granted permissions to " + uri);
5013
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005014 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005015
5016 final String authority = uri.getAuthority();
5017 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07005018 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005019 if (cpr != null) {
5020 pi = cpr.info;
5021 } else {
5022 try {
5023 pi = pm.resolveContentProvider(authority,
5024 PackageManager.GET_URI_PERMISSION_PATTERNS);
5025 } catch (RemoteException ex) {
5026 }
5027 }
5028 if (pi == null) {
Dianne Hackborn98cfebc2011-10-18 13:17:33 -07005029 Slog.w(TAG, "No content provider found for permission revoke: " + uri.toSafeString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005030 return;
5031 }
5032
5033 // Does the caller have this permission on the URI?
Dianne Hackborn48058e82010-09-27 16:53:23 -07005034 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005035 // Right now, if you are not the original owner of the permission,
5036 // you are not allowed to revoke it.
5037 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
5038 throw new SecurityException("Uid " + callingUid
5039 + " does not have permission to uri " + uri);
5040 //}
5041 }
5042
5043 // Go through all of the permissions and remove any that match.
5044 final List<String> SEGMENTS = uri.getPathSegments();
5045 if (SEGMENTS != null) {
5046 final int NS = SEGMENTS.size();
5047 int N = mGrantedUriPermissions.size();
5048 for (int i=0; i<N; i++) {
5049 HashMap<Uri, UriPermission> perms
5050 = mGrantedUriPermissions.valueAt(i);
5051 Iterator<UriPermission> it = perms.values().iterator();
5052 toploop:
5053 while (it.hasNext()) {
5054 UriPermission perm = it.next();
5055 Uri targetUri = perm.uri;
5056 if (!authority.equals(targetUri.getAuthority())) {
5057 continue;
5058 }
5059 List<String> targetSegments = targetUri.getPathSegments();
5060 if (targetSegments == null) {
5061 continue;
5062 }
5063 if (targetSegments.size() < NS) {
5064 continue;
5065 }
5066 for (int j=0; j<NS; j++) {
5067 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
5068 continue toploop;
5069 }
5070 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005071 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08005072 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005073 perm.clearModes(modeFlags);
5074 if (perm.modeFlags == 0) {
5075 it.remove();
5076 }
5077 }
5078 if (perms.size() == 0) {
5079 mGrantedUriPermissions.remove(
5080 mGrantedUriPermissions.keyAt(i));
5081 N--;
5082 i--;
5083 }
5084 }
5085 }
5086 }
5087
5088 public void revokeUriPermission(IApplicationThread caller, Uri uri,
5089 int modeFlags) {
5090 synchronized(this) {
5091 final ProcessRecord r = getRecordForAppLocked(caller);
5092 if (r == null) {
5093 throw new SecurityException("Unable to find app for caller "
5094 + caller
5095 + " when revoking permission to uri " + uri);
5096 }
5097 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005098 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005099 return;
5100 }
5101
5102 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
5103 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
5104 if (modeFlags == 0) {
5105 return;
5106 }
5107
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005108 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005109
5110 final String authority = uri.getAuthority();
5111 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07005112 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005113 if (cpr != null) {
5114 pi = cpr.info;
5115 } else {
5116 try {
5117 pi = pm.resolveContentProvider(authority,
5118 PackageManager.GET_URI_PERMISSION_PATTERNS);
5119 } catch (RemoteException ex) {
5120 }
5121 }
5122 if (pi == null) {
Dianne Hackborn98cfebc2011-10-18 13:17:33 -07005123 Slog.w(TAG, "No content provider found for permission revoke: "
5124 + uri.toSafeString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005125 return;
5126 }
5127
5128 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
5129 }
5130 }
5131
Dianne Hackborn7e269642010-08-25 19:50:20 -07005132 @Override
5133 public IBinder newUriPermissionOwner(String name) {
5134 synchronized(this) {
5135 UriPermissionOwner owner = new UriPermissionOwner(this, name);
5136 return owner.getExternalTokenLocked();
5137 }
5138 }
5139
5140 @Override
5141 public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg,
5142 Uri uri, int modeFlags) {
5143 synchronized(this) {
5144 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
5145 if (owner == null) {
5146 throw new IllegalArgumentException("Unknown owner: " + token);
5147 }
5148 if (fromUid != Binder.getCallingUid()) {
5149 if (Binder.getCallingUid() != Process.myUid()) {
5150 // Only system code can grant URI permissions on behalf
5151 // of other users.
5152 throw new SecurityException("nice try");
5153 }
5154 }
5155 if (targetPkg == null) {
5156 throw new IllegalArgumentException("null target");
5157 }
5158 if (uri == null) {
5159 throw new IllegalArgumentException("null uri");
5160 }
5161
5162 grantUriPermissionLocked(fromUid, targetPkg, uri, modeFlags, owner);
5163 }
5164 }
5165
5166 @Override
5167 public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode) {
5168 synchronized(this) {
5169 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
5170 if (owner == null) {
5171 throw new IllegalArgumentException("Unknown owner: " + token);
5172 }
5173
5174 if (uri == null) {
5175 owner.removeUriPermissionsLocked(mode);
5176 } else {
5177 owner.removeUriPermissionLocked(uri, mode);
5178 }
5179 }
5180 }
5181
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005182 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
5183 synchronized (this) {
5184 ProcessRecord app =
5185 who != null ? getRecordForAppLocked(who) : null;
5186 if (app == null) return;
5187
5188 Message msg = Message.obtain();
5189 msg.what = WAIT_FOR_DEBUGGER_MSG;
5190 msg.obj = app;
5191 msg.arg1 = waiting ? 1 : 0;
5192 mHandler.sendMessage(msg);
5193 }
5194 }
5195
5196 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
Dianne Hackborn7d608422011-08-07 16:24:18 -07005197 final long homeAppMem = mProcessList.getMemLevel(ProcessList.HOME_APP_ADJ);
5198 final long hiddenAppMem = mProcessList.getMemLevel(ProcessList.HIDDEN_APP_MIN_ADJ);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005199 outInfo.availMem = Process.getFreeMemory();
Dianne Hackborn7d608422011-08-07 16:24:18 -07005200 outInfo.threshold = homeAppMem;
5201 outInfo.lowMemory = outInfo.availMem < (homeAppMem + ((hiddenAppMem-homeAppMem)/2));
5202 outInfo.hiddenAppThreshold = hiddenAppMem;
5203 outInfo.secondaryServerThreshold = mProcessList.getMemLevel(
Dianne Hackborne02c88a2011-10-28 13:58:15 -07005204 ProcessList.SERVICE_ADJ);
Dianne Hackborn7d608422011-08-07 16:24:18 -07005205 outInfo.visibleAppThreshold = mProcessList.getMemLevel(
5206 ProcessList.VISIBLE_APP_ADJ);
5207 outInfo.foregroundAppThreshold = mProcessList.getMemLevel(
5208 ProcessList.FOREGROUND_APP_ADJ);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005209 }
5210
5211 // =========================================================
5212 // TASK MANAGEMENT
5213 // =========================================================
5214
5215 public List getTasks(int maxNum, int flags,
5216 IThumbnailReceiver receiver) {
5217 ArrayList list = new ArrayList();
5218
5219 PendingThumbnailsRecord pending = null;
5220 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005221 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005222
5223 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005224 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005225 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
5226 + ", receiver=" + receiver);
5227
5228 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
5229 != PackageManager.PERMISSION_GRANTED) {
5230 if (receiver != null) {
5231 // If the caller wants to wait for pending thumbnails,
5232 // it ain't gonna get them.
5233 try {
5234 receiver.finished();
5235 } catch (RemoteException ex) {
5236 }
5237 }
5238 String msg = "Permission Denial: getTasks() from pid="
5239 + Binder.getCallingPid()
5240 + ", uid=" + Binder.getCallingUid()
5241 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005242 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005243 throw new SecurityException(msg);
5244 }
5245
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005246 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005247 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005248 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005249 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005250 TaskRecord curTask = null;
5251 int numActivities = 0;
5252 int numRunning = 0;
5253 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005254 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005255 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005256 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005257
5258 // Initialize state for next task if needed.
5259 if (top == null ||
5260 (top.state == ActivityState.INITIALIZING
5261 && top.task == r.task)) {
5262 top = r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005263 curTask = r.task;
5264 numActivities = numRunning = 0;
5265 }
5266
5267 // Add 'r' into the current task.
5268 numActivities++;
5269 if (r.app != null && r.app.thread != null) {
5270 numRunning++;
5271 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005272
Joe Onorato8a9b2202010-02-26 18:56:32 -08005273 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005274 TAG, r.intent.getComponent().flattenToShortString()
5275 + ": task=" + r.task);
5276
5277 // If the next one is a different task, generate a new
5278 // TaskInfo entry for what we have.
5279 if (next == null || next.task != curTask) {
5280 ActivityManager.RunningTaskInfo ci
5281 = new ActivityManager.RunningTaskInfo();
5282 ci.id = curTask.taskId;
5283 ci.baseActivity = r.intent.getComponent();
5284 ci.topActivity = top.intent.getComponent();
Dianne Hackbornf26fd992011-04-08 18:14:09 -07005285 if (top.thumbHolder != null) {
5286 ci.description = top.thumbHolder.lastDescription;
5287 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005288 ci.numActivities = numActivities;
5289 ci.numRunning = numRunning;
5290 //System.out.println(
5291 // "#" + maxNum + ": " + " descr=" + ci.description);
5292 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005293 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005294 TAG, "State=" + top.state + "Idle=" + top.idle
5295 + " app=" + top.app
5296 + " thr=" + (top.app != null ? top.app.thread : null));
5297 if (top.state == ActivityState.RESUMED
5298 || top.state == ActivityState.PAUSING) {
5299 if (top.idle && top.app != null
5300 && top.app.thread != null) {
5301 topRecord = top;
5302 topThumbnail = top.app.thread;
5303 } else {
5304 top.thumbnailNeeded = true;
5305 }
5306 }
5307 if (pending == null) {
5308 pending = new PendingThumbnailsRecord(receiver);
5309 }
5310 pending.pendingRecords.add(top);
5311 }
5312 list.add(ci);
5313 maxNum--;
5314 top = null;
5315 }
5316 }
5317
5318 if (pending != null) {
5319 mPendingThumbnails.add(pending);
5320 }
5321 }
5322
Joe Onorato8a9b2202010-02-26 18:56:32 -08005323 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005324
5325 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005326 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005327 try {
Dianne Hackbornbe707852011-11-11 14:32:10 -08005328 topThumbnail.requestThumbnail(topRecord.appToken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005329 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005330 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
Dianne Hackbornbe707852011-11-11 14:32:10 -08005331 sendPendingThumbnail(null, topRecord.appToken, null, null, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005332 }
5333 }
5334
5335 if (pending == null && receiver != null) {
5336 // In this case all thumbnails were available and the client
5337 // is being asked to be told when the remaining ones come in...
5338 // which is unusually, since the top-most currently running
5339 // activity should never have a canned thumbnail! Oh well.
5340 try {
5341 receiver.finished();
5342 } catch (RemoteException ex) {
5343 }
5344 }
5345
5346 return list;
5347 }
5348
5349 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
5350 int flags) {
5351 synchronized (this) {
5352 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
5353 "getRecentTasks()");
5354
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005355 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07005356
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005357 final int N = mRecentTasks.size();
5358 ArrayList<ActivityManager.RecentTaskInfo> res
5359 = new ArrayList<ActivityManager.RecentTaskInfo>(
5360 maxNum < N ? maxNum : N);
5361 for (int i=0; i<N && maxNum > 0; i++) {
5362 TaskRecord tr = mRecentTasks.get(i);
Dianne Hackborn905577f2011-09-07 18:31:28 -07005363 // Return the entry if desired by the caller. We always return
5364 // the first entry, because callers always expect this to be the
5365 // forground app. We may filter others if the caller has
5366 // not supplied RECENT_WITH_EXCLUDED and there is some reason
5367 // we should exclude the entry.
5368 if (i == 0
5369 || ((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005370 || (tr.intent == null)
5371 || ((tr.intent.getFlags()
5372 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
5373 ActivityManager.RecentTaskInfo rti
5374 = new ActivityManager.RecentTaskInfo();
5375 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
Dianne Hackbornd94df452011-02-16 18:53:31 -08005376 rti.persistentId = tr.taskId;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005377 rti.baseIntent = new Intent(
5378 tr.intent != null ? tr.intent : tr.affinityIntent);
5379 rti.origActivity = tr.origActivity;
Dianne Hackbornd2835932010-12-13 16:28:46 -08005380 rti.description = tr.lastDescription;
5381
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07005382 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
5383 // Check whether this activity is currently available.
5384 try {
5385 if (rti.origActivity != null) {
5386 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
5387 continue;
5388 }
5389 } else if (rti.baseIntent != null) {
5390 if (pm.queryIntentActivities(rti.baseIntent,
5391 null, 0) == null) {
5392 continue;
5393 }
5394 }
5395 } catch (RemoteException e) {
5396 // Will never happen.
5397 }
5398 }
5399
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005400 res.add(rti);
5401 maxNum--;
5402 }
5403 }
5404 return res;
5405 }
5406 }
5407
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005408 private TaskRecord taskForIdLocked(int id) {
5409 final int N = mRecentTasks.size();
5410 for (int i=0; i<N; i++) {
5411 TaskRecord tr = mRecentTasks.get(i);
5412 if (tr.taskId == id) {
5413 return tr;
Dianne Hackbornd94df452011-02-16 18:53:31 -08005414 }
5415 }
5416 return null;
5417 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005418
5419 public ActivityManager.TaskThumbnails getTaskThumbnails(int id) {
5420 synchronized (this) {
5421 enforceCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER,
5422 "getTaskThumbnails()");
5423 TaskRecord tr = taskForIdLocked(id);
5424 if (tr != null) {
5425 return mMainStack.getTaskThumbnailsLocked(tr);
5426 }
5427 }
5428 return null;
5429 }
5430
5431 public boolean removeSubTask(int taskId, int subTaskIndex) {
5432 synchronized (this) {
5433 enforceCallingPermission(android.Manifest.permission.REMOVE_TASKS,
5434 "removeSubTask()");
5435 long ident = Binder.clearCallingIdentity();
5436 try {
5437 return mMainStack.removeTaskActivitiesLocked(taskId, subTaskIndex) != null;
5438 } finally {
5439 Binder.restoreCallingIdentity(ident);
5440 }
5441 }
5442 }
5443
Dianne Hackborn8894cc52011-07-01 16:28:17 -07005444 private void cleanUpRemovedTaskLocked(ActivityRecord root, boolean killProcesses) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005445 TaskRecord tr = root.task;
5446 Intent baseIntent = new Intent(
5447 tr.intent != null ? tr.intent : tr.affinityIntent);
5448 ComponentName component = baseIntent.getComponent();
5449 if (component == null) {
5450 Slog.w(TAG, "Now component for base intent of task: " + tr);
5451 return;
5452 }
5453
5454 // Find any running services associated with this app.
5455 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
5456 for (ServiceRecord sr : mServices.values()) {
5457 if (sr.packageName.equals(component.getPackageName())) {
5458 services.add(sr);
5459 }
5460 }
5461
5462 // Take care of any running services associated with the app.
5463 for (int i=0; i<services.size(); i++) {
5464 ServiceRecord sr = services.get(i);
5465 if (sr.startRequested) {
5466 if ((sr.serviceInfo.flags&ServiceInfo.FLAG_STOP_WITH_TASK) != 0) {
Dianne Hackborn8894cc52011-07-01 16:28:17 -07005467 Slog.i(TAG, "Stopping service " + sr.shortName + ": remove task");
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005468 stopServiceLocked(sr);
5469 } else {
5470 sr.pendingStarts.add(new ServiceRecord.StartItem(sr, true,
5471 sr.makeNextStartId(), baseIntent, -1));
5472 if (sr.app != null && sr.app.thread != null) {
5473 sendServiceArgsLocked(sr, false);
5474 }
5475 }
5476 }
5477 }
5478
Dianne Hackborn8894cc52011-07-01 16:28:17 -07005479 if (killProcesses) {
5480 // Find any running processes associated with this app.
5481 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
5482 SparseArray<ProcessRecord> appProcs
5483 = mProcessNames.getMap().get(component.getPackageName());
5484 if (appProcs != null) {
5485 for (int i=0; i<appProcs.size(); i++) {
5486 procs.add(appProcs.valueAt(i));
5487 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005488 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005489
Dianne Hackborn8894cc52011-07-01 16:28:17 -07005490 // Kill the running processes.
5491 for (int i=0; i<procs.size(); i++) {
5492 ProcessRecord pr = procs.get(i);
5493 if (pr.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {
5494 Slog.i(TAG, "Killing " + pr.toShortString() + ": remove task");
5495 EventLog.writeEvent(EventLogTags.AM_KILL, pr.pid,
5496 pr.processName, pr.setAdj, "remove task");
5497 Process.killProcessQuiet(pr.pid);
5498 } else {
5499 pr.waitingToKill = "remove task";
5500 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005501 }
5502 }
5503 }
5504
5505 public boolean removeTask(int taskId, int flags) {
5506 synchronized (this) {
5507 enforceCallingPermission(android.Manifest.permission.REMOVE_TASKS,
5508 "removeTask()");
5509 long ident = Binder.clearCallingIdentity();
5510 try {
5511 ActivityRecord r = mMainStack.removeTaskActivitiesLocked(taskId, -1);
5512 if (r != null) {
5513 mRecentTasks.remove(r.task);
Dianne Hackborn8894cc52011-07-01 16:28:17 -07005514 cleanUpRemovedTaskLocked(r,
5515 (flags&ActivityManager.REMOVE_TASK_KILL_PROCESS) != 0);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005516 return true;
Dianne Hackborneeb1dca2011-09-08 13:30:11 -07005517 } else {
5518 TaskRecord tr = null;
5519 int i=0;
5520 while (i < mRecentTasks.size()) {
5521 TaskRecord t = mRecentTasks.get(i);
5522 if (t.taskId == taskId) {
5523 tr = t;
5524 break;
5525 }
5526 i++;
5527 }
5528 if (tr != null) {
5529 if (tr.numActivities <= 0) {
5530 // Caller is just removing a recent task that is
5531 // not actively running. That is easy!
5532 mRecentTasks.remove(i);
5533 } else {
5534 Slog.w(TAG, "removeTask: task " + taskId
5535 + " does not have activities to remove, "
5536 + " but numActivities=" + tr.numActivities
5537 + ": " + tr);
5538 }
5539 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005540 }
5541 } finally {
5542 Binder.restoreCallingIdentity(ident);
5543 }
5544 }
5545 return false;
5546 }
Dianne Hackbornd94df452011-02-16 18:53:31 -08005547
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005548 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
5549 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005550 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005551 TaskRecord jt = startTask;
5552
5553 // First look backwards
5554 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005555 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005556 if (r.task != jt) {
5557 jt = r.task;
5558 if (affinity.equals(jt.affinity)) {
5559 return j;
5560 }
5561 }
5562 }
5563
5564 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005565 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005566 jt = startTask;
5567 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005568 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005569 if (r.task != jt) {
5570 if (affinity.equals(jt.affinity)) {
5571 return j;
5572 }
5573 jt = r.task;
5574 }
5575 }
5576
5577 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005578 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005579 return N-1;
5580 }
5581
5582 return -1;
5583 }
5584
5585 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005586 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005587 */
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005588 public void moveTaskToFront(int task, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005589 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5590 "moveTaskToFront()");
5591
5592 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005593 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5594 Binder.getCallingUid(), "Task to front")) {
5595 return;
5596 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005597 final long origId = Binder.clearCallingIdentity();
5598 try {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005599 TaskRecord tr = taskForIdLocked(task);
5600 if (tr != null) {
5601 if ((flags&ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
5602 mMainStack.mUserLeaving = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005603 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005604 if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
5605 // Caller wants the home activity moved with it. To accomplish this,
5606 // we'll just move the home task to the top first.
5607 mMainStack.moveHomeToFrontLocked();
5608 }
5609 mMainStack.moveTaskToFrontLocked(tr, null);
5610 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005611 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005612 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
5613 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005614 if (hr.task.taskId == task) {
Dianne Hackbornd94df452011-02-16 18:53:31 -08005615 if ((flags&ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
5616 mMainStack.mUserLeaving = true;
5617 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005618 if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
5619 // Caller wants the home activity moved with it. To accomplish this,
5620 // we'll just move the home task to the top first.
5621 mMainStack.moveHomeToFrontLocked();
5622 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005623 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005624 return;
5625 }
5626 }
5627 } finally {
5628 Binder.restoreCallingIdentity(origId);
5629 }
5630 }
5631 }
5632
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005633 public void moveTaskToBack(int task) {
5634 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5635 "moveTaskToBack()");
5636
5637 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005638 if (mMainStack.mResumedActivity != null
5639 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005640 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5641 Binder.getCallingUid(), "Task to back")) {
5642 return;
5643 }
5644 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005645 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005646 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005647 Binder.restoreCallingIdentity(origId);
5648 }
5649 }
5650
5651 /**
5652 * Moves an activity, and all of the other activities within the same task, to the bottom
5653 * of the history stack. The activity's order within the task is unchanged.
5654 *
5655 * @param token A reference to the activity we wish to move
5656 * @param nonRoot If false then this only works if the activity is the root
5657 * of a task; if true it will work for any activity in a task.
5658 * @return Returns true if the move completed, false if not.
5659 */
5660 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
5661 synchronized(this) {
5662 final long origId = Binder.clearCallingIdentity();
5663 int taskId = getTaskForActivityLocked(token, !nonRoot);
5664 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005665 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005666 }
5667 Binder.restoreCallingIdentity(origId);
5668 }
5669 return false;
5670 }
5671
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005672 public void moveTaskBackwards(int task) {
5673 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5674 "moveTaskBackwards()");
5675
5676 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005677 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5678 Binder.getCallingUid(), "Task backwards")) {
5679 return;
5680 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005681 final long origId = Binder.clearCallingIdentity();
5682 moveTaskBackwardsLocked(task);
5683 Binder.restoreCallingIdentity(origId);
5684 }
5685 }
5686
5687 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005688 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005689 }
5690
5691 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
5692 synchronized(this) {
5693 return getTaskForActivityLocked(token, onlyRoot);
5694 }
5695 }
5696
5697 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005698 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005699 TaskRecord lastTask = null;
5700 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005701 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackbornbe707852011-11-11 14:32:10 -08005702 if (r.appToken == token) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005703 if (!onlyRoot || lastTask != r.task) {
5704 return r.task.taskId;
5705 }
5706 return -1;
5707 }
5708 lastTask = r.task;
5709 }
5710
5711 return -1;
5712 }
5713
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005714 public void finishOtherInstances(IBinder token, ComponentName className) {
5715 synchronized(this) {
5716 final long origId = Binder.clearCallingIdentity();
5717
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005718 int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005719 TaskRecord lastTask = null;
5720 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005721 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005722 if (r.realActivity.equals(className)
Dianne Hackbornbe707852011-11-11 14:32:10 -08005723 && r.appToken != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005724 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005725 null, "others")) {
5726 i--;
5727 N--;
5728 }
5729 }
5730 lastTask = r.task;
5731 }
5732
5733 Binder.restoreCallingIdentity(origId);
5734 }
5735 }
5736
5737 // =========================================================
5738 // THUMBNAILS
5739 // =========================================================
5740
5741 public void reportThumbnail(IBinder token,
5742 Bitmap thumbnail, CharSequence description) {
5743 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
5744 final long origId = Binder.clearCallingIdentity();
5745 sendPendingThumbnail(null, token, thumbnail, description, true);
5746 Binder.restoreCallingIdentity(origId);
5747 }
5748
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005749 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005750 Bitmap thumbnail, CharSequence description, boolean always) {
5751 TaskRecord task = null;
5752 ArrayList receivers = null;
5753
5754 //System.out.println("Send pending thumbnail: " + r);
5755
5756 synchronized(this) {
5757 if (r == null) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07005758 r = mMainStack.isInStackLocked(token);
5759 if (r == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005760 return;
5761 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005762 }
Dianne Hackbornf26fd992011-04-08 18:14:09 -07005763 if (thumbnail == null && r.thumbHolder != null) {
5764 thumbnail = r.thumbHolder.lastThumbnail;
5765 description = r.thumbHolder.lastDescription;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005766 }
5767 if (thumbnail == null && !always) {
5768 // If there is no thumbnail, and this entry is not actually
5769 // going away, then abort for now and pick up the next
5770 // thumbnail we get.
5771 return;
5772 }
5773 task = r.task;
5774
5775 int N = mPendingThumbnails.size();
5776 int i=0;
5777 while (i<N) {
5778 PendingThumbnailsRecord pr =
5779 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
5780 //System.out.println("Looking in " + pr.pendingRecords);
5781 if (pr.pendingRecords.remove(r)) {
5782 if (receivers == null) {
5783 receivers = new ArrayList();
5784 }
5785 receivers.add(pr);
5786 if (pr.pendingRecords.size() == 0) {
5787 pr.finished = true;
5788 mPendingThumbnails.remove(i);
5789 N--;
5790 continue;
5791 }
5792 }
5793 i++;
5794 }
5795 }
5796
5797 if (receivers != null) {
5798 final int N = receivers.size();
5799 for (int i=0; i<N; i++) {
5800 try {
5801 PendingThumbnailsRecord pr =
5802 (PendingThumbnailsRecord)receivers.get(i);
5803 pr.receiver.newThumbnail(
5804 task != null ? task.taskId : -1, thumbnail, description);
5805 if (pr.finished) {
5806 pr.receiver.finished();
5807 }
5808 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005809 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005810 }
5811 }
5812 }
5813 }
5814
5815 // =========================================================
5816 // CONTENT PROVIDERS
5817 // =========================================================
5818
Jeff Brown10e89712011-07-08 18:52:57 -07005819 private final List<ProviderInfo> generateApplicationProvidersLocked(ProcessRecord app) {
5820 List<ProviderInfo> providers = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005821 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005822 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005823 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005824 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005825 } catch (RemoteException ex) {
5826 }
5827 if (providers != null) {
5828 final int N = providers.size();
5829 for (int i=0; i<N; i++) {
5830 ProviderInfo cpi =
5831 (ProviderInfo)providers.get(i);
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07005832 ComponentName comp = new ComponentName(cpi.packageName, cpi.name);
5833 ContentProviderRecord cpr = mProvidersByClass.get(comp);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005834 if (cpr == null) {
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07005835 cpr = new ContentProviderRecord(cpi, app.info, comp);
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07005836 mProvidersByClass.put(comp, cpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005837 }
5838 app.pubProviders.put(cpi.name, cpr);
5839 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005840 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005841 }
5842 }
5843 return providers;
5844 }
5845
5846 private final String checkContentProviderPermissionLocked(
Dianne Hackbornb424b632010-08-18 15:59:05 -07005847 ProviderInfo cpi, ProcessRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005848 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
5849 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
5850 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005851 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005852 == PackageManager.PERMISSION_GRANTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005853 return null;
5854 }
5855 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005856 cpi.applicationInfo.uid, cpi.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005857 == PackageManager.PERMISSION_GRANTED) {
5858 return null;
5859 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005860
5861 PathPermission[] pps = cpi.pathPermissions;
5862 if (pps != null) {
5863 int i = pps.length;
5864 while (i > 0) {
5865 i--;
5866 PathPermission pp = pps[i];
5867 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005868 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005869 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005870 return null;
5871 }
5872 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005873 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005874 == PackageManager.PERMISSION_GRANTED) {
5875 return null;
5876 }
5877 }
5878 }
5879
Dianne Hackbornb424b632010-08-18 15:59:05 -07005880 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
5881 if (perms != null) {
5882 for (Map.Entry<Uri, UriPermission> uri : perms.entrySet()) {
5883 if (uri.getKey().getAuthority().equals(cpi.authority)) {
5884 return null;
5885 }
5886 }
5887 }
5888
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005889 String msg;
5890 if (!cpi.exported) {
5891 msg = "Permission Denial: opening provider " + cpi.name
5892 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5893 + ", uid=" + callingUid + ") that is not exported from uid "
5894 + cpi.applicationInfo.uid;
5895 } else {
5896 msg = "Permission Denial: opening provider " + cpi.name
5897 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5898 + ", uid=" + callingUid + ") requires "
5899 + cpi.readPermission + " or " + cpi.writePermission;
5900 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005901 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005902 return msg;
5903 }
5904
Dianne Hackborn295e3c22011-08-25 13:19:08 -07005905 boolean incProviderCount(ProcessRecord r, ContentProviderRecord cpr) {
5906 if (r != null) {
5907 Integer cnt = r.conProviders.get(cpr);
5908 if (DEBUG_PROVIDER) Slog.v(TAG,
5909 "Adding provider requested by "
5910 + r.processName + " from process "
5911 + cpr.info.processName + ": " + cpr.name.flattenToShortString()
5912 + " cnt=" + (cnt == null ? 1 : cnt));
5913 if (cnt == null) {
5914 cpr.clients.add(r);
5915 r.conProviders.put(cpr, new Integer(1));
5916 return true;
5917 } else {
5918 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5919 }
5920 } else {
5921 cpr.externals++;
5922 }
5923 return false;
5924 }
5925
5926 boolean decProviderCount(ProcessRecord r, ContentProviderRecord cpr) {
5927 if (r != null) {
5928 Integer cnt = r.conProviders.get(cpr);
5929 if (DEBUG_PROVIDER) Slog.v(TAG,
5930 "Removing provider requested by "
5931 + r.processName + " from process "
5932 + cpr.info.processName + ": " + cpr.name.flattenToShortString()
5933 + " cnt=" + cnt);
5934 if (cnt == null || cnt.intValue() <= 1) {
5935 cpr.clients.remove(r);
5936 r.conProviders.remove(cpr);
5937 return true;
5938 } else {
5939 r.conProviders.put(cpr, new Integer(cnt.intValue()-1));
5940 }
5941 } else {
5942 cpr.externals++;
5943 }
5944 return false;
5945 }
5946
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005947 private final ContentProviderHolder getContentProviderImpl(
5948 IApplicationThread caller, String name) {
5949 ContentProviderRecord cpr;
5950 ProviderInfo cpi = null;
5951
5952 synchronized(this) {
5953 ProcessRecord r = null;
5954 if (caller != null) {
5955 r = getRecordForAppLocked(caller);
5956 if (r == null) {
5957 throw new SecurityException(
5958 "Unable to find app for caller " + caller
5959 + " (pid=" + Binder.getCallingPid()
5960 + ") when getting content provider " + name);
5961 }
5962 }
5963
5964 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07005965 cpr = mProvidersByName.get(name);
Dianne Hackborn295e3c22011-08-25 13:19:08 -07005966 boolean providerRunning = cpr != null;
5967 if (providerRunning) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005968 cpi = cpr.info;
Dianne Hackbornb424b632010-08-18 15:59:05 -07005969 String msg;
5970 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5971 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005972 }
5973
5974 if (r != null && cpr.canRunHere(r)) {
5975 // This provider has been published or is in the process
5976 // of being published... but it is also allowed to run
5977 // in the caller's process, so don't make a connection
5978 // and just let the caller instantiate its own instance.
5979 if (cpr.provider != null) {
5980 // don't give caller the provider object, it needs
5981 // to make its own.
5982 cpr = new ContentProviderRecord(cpr);
5983 }
5984 return cpr;
5985 }
5986
5987 final long origId = Binder.clearCallingIdentity();
5988
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005989 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005990 // return it right away.
Dianne Hackborn295e3c22011-08-25 13:19:08 -07005991 final boolean countChanged = incProviderCount(r, cpr);
5992 if (countChanged) {
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07005993 if (cpr.proc != null && r.setAdj <= ProcessList.PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -07005994 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07005995 // make sure to count it as being accessed and thus
5996 // back up on the LRU list. This is good because
5997 // content providers are often expensive to start.
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07005998 updateLruProcessLocked(cpr.proc, false, true);
Dianne Hackborn906497c2010-05-10 15:57:38 -07005999 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07006000 }
6001
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07006002 if (cpr.proc != null) {
Dianne Hackborn295e3c22011-08-25 13:19:08 -07006003 if (false) {
6004 if (cpr.name.flattenToShortString().equals(
6005 "com.android.providers.calendar/.CalendarProvider2")) {
6006 Slog.v(TAG, "****************** KILLING "
6007 + cpr.name.flattenToShortString());
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07006008 Process.killProcess(cpr.proc.pid);
Dianne Hackborn295e3c22011-08-25 13:19:08 -07006009 }
6010 }
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07006011 boolean success = updateOomAdjLocked(cpr.proc);
Dianne Hackborn295e3c22011-08-25 13:19:08 -07006012 if (DEBUG_PROVIDER) Slog.i(TAG, "Adjust success: " + success);
6013 // NOTE: there is still a race here where a signal could be
6014 // pending on the process even though we managed to update its
6015 // adj level. Not sure what to do about this, but at least
6016 // the race is now smaller.
6017 if (!success) {
6018 // Uh oh... it looks like the provider's process
6019 // has been killed on us. We need to wait for a new
6020 // process to be started, and make sure its death
6021 // doesn't kill our process.
6022 Slog.i(TAG,
6023 "Existing provider " + cpr.name.flattenToShortString()
6024 + " is crashing; detaching " + r);
6025 boolean lastRef = decProviderCount(r, cpr);
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07006026 appDiedLocked(cpr.proc, cpr.proc.pid, cpr.proc.thread);
Dianne Hackborn295e3c22011-08-25 13:19:08 -07006027 if (!lastRef) {
6028 // This wasn't the last ref our process had on
6029 // the provider... we have now been killed, bail.
6030 return null;
6031 }
6032 providerRunning = false;
6033 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006034 }
6035
6036 Binder.restoreCallingIdentity(origId);
Dianne Hackborn295e3c22011-08-25 13:19:08 -07006037 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006038
Dianne Hackborn295e3c22011-08-25 13:19:08 -07006039 if (!providerRunning) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006040 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006041 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07006042 resolveContentProvider(name,
6043 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006044 } catch (RemoteException ex) {
6045 }
6046 if (cpi == null) {
6047 return null;
6048 }
6049
Dianne Hackbornb424b632010-08-18 15:59:05 -07006050 String msg;
6051 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
6052 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006053 }
6054
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07006055 if (!mProcessesReady && !mDidUpdate && !mWaitingUpdate
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08006056 && !cpi.processName.equals("system")) {
6057 // If this content provider does not run in the system
6058 // process, and the system is not yet ready to run other
6059 // processes, then fail fast instead of hanging.
6060 throw new IllegalArgumentException(
6061 "Attempt to launch content provider before system ready");
6062 }
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07006063
6064 ComponentName comp = new ComponentName(cpi.packageName, cpi.name);
6065 cpr = mProvidersByClass.get(comp);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006066 final boolean firstClass = cpr == null;
6067 if (firstClass) {
6068 try {
6069 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006070 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006071 getApplicationInfo(
6072 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07006073 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006074 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006075 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006076 + cpi.name);
6077 return null;
6078 }
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07006079 cpr = new ContentProviderRecord(cpi, ai, comp);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006080 } catch (RemoteException ex) {
6081 // pm is in same process, this will never happen.
6082 }
6083 }
6084
6085 if (r != null && cpr.canRunHere(r)) {
6086 // If this is a multiprocess provider, then just return its
6087 // info and allow the caller to instantiate it. Only do
6088 // this if the provider is the same user as the caller's
6089 // process, or can run as root (so can be in any process).
6090 return cpr;
6091 }
6092
Dianne Hackborna1e989b2009-09-01 19:54:29 -07006093 if (DEBUG_PROVIDER) {
6094 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08006095 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07006096 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006097 }
6098
6099 // This is single process, and our app is now connecting to it.
6100 // See if we are already in the process of launching this
6101 // provider.
6102 final int N = mLaunchingProviders.size();
6103 int i;
6104 for (i=0; i<N; i++) {
6105 if (mLaunchingProviders.get(i) == cpr) {
6106 break;
6107 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006108 }
6109
6110 // If the provider is not already being launched, then get it
6111 // started.
6112 if (i >= N) {
6113 final long origId = Binder.clearCallingIdentity();
Dianne Hackborne7f97212011-02-24 14:40:20 -08006114
6115 try {
6116 // Content provider is now in use, its package can't be stopped.
6117 try {
6118 AppGlobals.getPackageManager().setPackageStoppedState(
6119 cpr.appInfo.packageName, false);
6120 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08006121 } catch (IllegalArgumentException e) {
6122 Slog.w(TAG, "Failed trying to unstop package "
6123 + cpr.appInfo.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08006124 }
6125
6126 ProcessRecord proc = startProcessLocked(cpi.processName,
6127 cpr.appInfo, false, 0, "content provider",
6128 new ComponentName(cpi.applicationInfo.packageName,
6129 cpi.name), false);
6130 if (proc == null) {
6131 Slog.w(TAG, "Unable to launch app "
6132 + cpi.applicationInfo.packageName + "/"
6133 + cpi.applicationInfo.uid + " for provider "
6134 + name + ": process is bad");
6135 return null;
6136 }
6137 cpr.launchingApp = proc;
6138 mLaunchingProviders.add(cpr);
6139 } finally {
6140 Binder.restoreCallingIdentity(origId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006141 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006142 }
6143
6144 // Make sure the provider is published (the same provider class
6145 // may be published under multiple names).
6146 if (firstClass) {
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07006147 mProvidersByClass.put(comp, cpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006148 }
6149 mProvidersByName.put(name, cpr);
Dianne Hackborn295e3c22011-08-25 13:19:08 -07006150 incProviderCount(r, cpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006151 }
6152 }
6153
6154 // Wait for the provider to be published...
6155 synchronized (cpr) {
6156 while (cpr.provider == null) {
6157 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006158 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006159 + cpi.applicationInfo.packageName + "/"
6160 + cpi.applicationInfo.uid + " for provider "
6161 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006162 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006163 cpi.applicationInfo.packageName,
6164 cpi.applicationInfo.uid, name);
6165 return null;
6166 }
6167 try {
6168 cpr.wait();
6169 } catch (InterruptedException ex) {
6170 }
6171 }
6172 }
6173 return cpr;
6174 }
6175
6176 public final ContentProviderHolder getContentProvider(
6177 IApplicationThread caller, String name) {
6178 if (caller == null) {
6179 String msg = "null IApplicationThread when getting content provider "
6180 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006181 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006182 throw new SecurityException(msg);
6183 }
6184
6185 return getContentProviderImpl(caller, name);
6186 }
6187
6188 private ContentProviderHolder getContentProviderExternal(String name) {
6189 return getContentProviderImpl(null, name);
6190 }
6191
6192 /**
6193 * Drop a content provider from a ProcessRecord's bookkeeping
6194 * @param cpr
6195 */
6196 public void removeContentProvider(IApplicationThread caller, String name) {
6197 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006198 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006199 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07006200 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08006201 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07006202 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006203 return;
6204 }
6205 final ProcessRecord r = getRecordForAppLocked(caller);
6206 if (r == null) {
6207 throw new SecurityException(
6208 "Unable to find app for caller " + caller +
6209 " when removing content provider " + name);
6210 }
6211 //update content provider record entry info
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07006212 ComponentName comp = new ComponentName(cpr.info.packageName, cpr.info.name);
6213 ContentProviderRecord localCpr = mProvidersByClass.get(comp);
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07006214 if (localCpr.proc == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006215 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08006216 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07006217 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006218 return;
6219 } else {
Dianne Hackborn295e3c22011-08-25 13:19:08 -07006220 if (decProviderCount(r, localCpr)) {
6221 updateOomAdjLocked();
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07006222 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006223 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006224 }
6225 }
6226
6227 private void removeContentProviderExternal(String name) {
6228 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006229 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006230 if(cpr == null) {
6231 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08006232 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006233 return;
6234 }
6235
6236 //update content provider record entry info
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07006237 ComponentName comp = new ComponentName(cpr.info.packageName, cpr.info.name);
6238 ContentProviderRecord localCpr = mProvidersByClass.get(comp);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006239 localCpr.externals--;
6240 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006241 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006242 }
6243 updateOomAdjLocked();
6244 }
6245 }
6246
6247 public final void publishContentProviders(IApplicationThread caller,
6248 List<ContentProviderHolder> providers) {
6249 if (providers == null) {
6250 return;
6251 }
6252
6253 synchronized(this) {
6254 final ProcessRecord r = getRecordForAppLocked(caller);
6255 if (r == null) {
6256 throw new SecurityException(
6257 "Unable to find app for caller " + caller
6258 + " (pid=" + Binder.getCallingPid()
6259 + ") when publishing content providers");
6260 }
6261
6262 final long origId = Binder.clearCallingIdentity();
6263
6264 final int N = providers.size();
6265 for (int i=0; i<N; i++) {
6266 ContentProviderHolder src = providers.get(i);
6267 if (src == null || src.info == null || src.provider == null) {
6268 continue;
6269 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07006270 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006271 if (dst != null) {
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07006272 ComponentName comp = new ComponentName(dst.info.packageName, dst.info.name);
6273 mProvidersByClass.put(comp, dst);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006274 String names[] = dst.info.authority.split(";");
6275 for (int j = 0; j < names.length; j++) {
6276 mProvidersByName.put(names[j], dst);
6277 }
6278
6279 int NL = mLaunchingProviders.size();
6280 int j;
6281 for (j=0; j<NL; j++) {
6282 if (mLaunchingProviders.get(j) == dst) {
6283 mLaunchingProviders.remove(j);
6284 j--;
6285 NL--;
6286 }
6287 }
6288 synchronized (dst) {
6289 dst.provider = src.provider;
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07006290 dst.proc = r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006291 dst.notifyAll();
6292 }
6293 updateOomAdjLocked(r);
6294 }
6295 }
6296
6297 Binder.restoreCallingIdentity(origId);
6298 }
6299 }
6300
6301 public static final void installSystemProviders() {
Jeff Brown10e89712011-07-08 18:52:57 -07006302 List<ProviderInfo> providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06006303 synchronized (mSelf) {
6304 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
6305 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08006306 if (providers != null) {
6307 for (int i=providers.size()-1; i>=0; i--) {
6308 ProviderInfo pi = (ProviderInfo)providers.get(i);
6309 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
6310 Slog.w(TAG, "Not installing system proc provider " + pi.name
6311 + ": not system .apk");
6312 providers.remove(i);
6313 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08006314 }
6315 }
6316 }
Josh Bartel2ecce342010-02-25 10:55:48 -06006317 if (providers != null) {
6318 mSystemThread.installSystemProviders(providers);
6319 }
Svetoslav Ganov54d068e2011-03-02 12:58:40 -08006320
6321 mSelf.mCoreSettingsObserver = new CoreSettingsObserver(mSelf);
Mark Brophyc6350272011-08-05 16:16:39 +01006322
6323 mSelf.mUsageStatsService.monitorPackages();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006324 }
6325
Dianne Hackborncca1f0e2010-09-26 18:34:53 -07006326 /**
6327 * Allows app to retrieve the MIME type of a URI without having permission
6328 * to access its content provider.
6329 *
6330 * CTS tests for this functionality can be run with "runtest cts-appsecurity".
6331 *
6332 * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
6333 * src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
6334 */
6335 public String getProviderMimeType(Uri uri) {
6336 final String name = uri.getAuthority();
6337 final long ident = Binder.clearCallingIdentity();
6338 ContentProviderHolder holder = null;
6339
6340 try {
6341 holder = getContentProviderExternal(name);
6342 if (holder != null) {
6343 return holder.provider.getType(uri);
6344 }
6345 } catch (RemoteException e) {
6346 Log.w(TAG, "Content provider dead retrieving " + uri, e);
6347 return null;
6348 } finally {
6349 if (holder != null) {
6350 removeContentProviderExternal(name);
6351 }
6352 Binder.restoreCallingIdentity(ident);
6353 }
6354
6355 return null;
6356 }
6357
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006358 // =========================================================
6359 // GLOBAL MANAGEMENT
6360 // =========================================================
6361
6362 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
6363 ApplicationInfo info, String customProcess) {
6364 String proc = customProcess != null ? customProcess : info.processName;
6365 BatteryStatsImpl.Uid.Proc ps = null;
6366 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
6367 synchronized (stats) {
6368 ps = stats.getProcessStatsLocked(info.uid, proc);
6369 }
6370 return new ProcessRecord(ps, thread, info, proc);
6371 }
6372
6373 final ProcessRecord addAppLocked(ApplicationInfo info) {
6374 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
6375
6376 if (app == null) {
6377 app = newProcessRecordLocked(null, info, null);
6378 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006379 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006380 }
6381
Dianne Hackborne7f97212011-02-24 14:40:20 -08006382 // This package really, really can not be stopped.
6383 try {
6384 AppGlobals.getPackageManager().setPackageStoppedState(
6385 info.packageName, false);
6386 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08006387 } catch (IllegalArgumentException e) {
6388 Slog.w(TAG, "Failed trying to unstop package "
6389 + info.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08006390 }
6391
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006392 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
6393 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
6394 app.persistent = true;
Dianne Hackborne02c88a2011-10-28 13:58:15 -07006395 app.maxAdj = ProcessList.PERSISTENT_PROC_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006396 }
6397 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
6398 mPersistentStartingProcesses.add(app);
6399 startProcessLocked(app, "added application", app.processName);
6400 }
6401
6402 return app;
6403 }
6404
6405 public void unhandledBack() {
6406 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
6407 "unhandledBack()");
6408
6409 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006410 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08006411 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006412 TAG, "Performing unhandledBack(): stack size = " + count);
6413 if (count > 1) {
6414 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006415 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006416 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
6417 Binder.restoreCallingIdentity(origId);
6418 }
6419 }
6420 }
6421
6422 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
6423 String name = uri.getAuthority();
6424 ContentProviderHolder cph = getContentProviderExternal(name);
6425 ParcelFileDescriptor pfd = null;
6426 if (cph != null) {
6427 // We record the binder invoker's uid in thread-local storage before
6428 // going to the content provider to open the file. Later, in the code
6429 // that handles all permissions checks, we look for this uid and use
6430 // that rather than the Activity Manager's own uid. The effect is that
6431 // we do the check against the caller's permissions even though it looks
6432 // to the content provider like the Activity Manager itself is making
6433 // the request.
6434 sCallerIdentity.set(new Identity(
6435 Binder.getCallingPid(), Binder.getCallingUid()));
6436 try {
6437 pfd = cph.provider.openFile(uri, "r");
6438 } catch (FileNotFoundException e) {
6439 // do nothing; pfd will be returned null
6440 } finally {
6441 // Ensure that whatever happens, we clean up the identity state
6442 sCallerIdentity.remove();
6443 }
6444
6445 // We've got the fd now, so we're done with the provider.
6446 removeContentProviderExternal(name);
6447 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006448 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006449 }
6450 return pfd;
6451 }
6452
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006453 // Actually is sleeping or shutting down or whatever else in the future
6454 // is an inactive state.
6455 public boolean isSleeping() {
6456 return mSleeping || mShuttingDown;
6457 }
6458
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006459 public void goingToSleep() {
6460 synchronized(this) {
6461 mSleeping = true;
6462 mWindowManager.setEventDispatching(false);
6463
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006464 mMainStack.stopIfSleepingLocked();
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07006465
6466 // Initialize the wake times of all processes.
Dianne Hackborn287952c2010-09-22 22:34:31 -07006467 checkExcessivePowerUsageLocked(false);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07006468 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
6469 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07006470 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006471 }
6472 }
6473
Dianne Hackborn55280a92009-05-07 15:53:46 -07006474 public boolean shutdown(int timeout) {
6475 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
6476 != PackageManager.PERMISSION_GRANTED) {
6477 throw new SecurityException("Requires permission "
6478 + android.Manifest.permission.SHUTDOWN);
6479 }
6480
6481 boolean timedout = false;
6482
6483 synchronized(this) {
6484 mShuttingDown = true;
6485 mWindowManager.setEventDispatching(false);
6486
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006487 if (mMainStack.mResumedActivity != null) {
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006488 mMainStack.stopIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07006489 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006490 while (mMainStack.mResumedActivity != null
6491 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07006492 long delay = endTime - System.currentTimeMillis();
6493 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006494 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07006495 timedout = true;
6496 break;
6497 }
6498 try {
6499 this.wait();
6500 } catch (InterruptedException e) {
6501 }
6502 }
6503 }
6504 }
6505
6506 mUsageStatsService.shutdown();
6507 mBatteryStatsService.shutdown();
6508
6509 return timedout;
6510 }
6511
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006512 public final void activitySlept(IBinder token) {
6513 if (localLOGV) Slog.v(
6514 TAG, "Activity slept: token=" + token);
6515
6516 ActivityRecord r = null;
6517
6518 final long origId = Binder.clearCallingIdentity();
6519
6520 synchronized (this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07006521 r = mMainStack.isInStackLocked(token);
6522 if (r != null) {
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006523 mMainStack.activitySleptLocked(r);
6524 }
6525 }
6526
6527 Binder.restoreCallingIdentity(origId);
6528 }
6529
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006530 public void wakingUp() {
6531 synchronized(this) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006532 mWindowManager.setEventDispatching(true);
6533 mSleeping = false;
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006534 mMainStack.awakeFromSleepingLocked();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006535 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006536 }
6537 }
6538
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006539 public void stopAppSwitches() {
6540 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
6541 != PackageManager.PERMISSION_GRANTED) {
6542 throw new SecurityException("Requires permission "
6543 + android.Manifest.permission.STOP_APP_SWITCHES);
6544 }
6545
6546 synchronized(this) {
6547 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
6548 + APP_SWITCH_DELAY_TIME;
6549 mDidAppSwitch = false;
6550 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
6551 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
6552 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
6553 }
6554 }
6555
6556 public void resumeAppSwitches() {
6557 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
6558 != PackageManager.PERMISSION_GRANTED) {
6559 throw new SecurityException("Requires permission "
6560 + android.Manifest.permission.STOP_APP_SWITCHES);
6561 }
6562
6563 synchronized(this) {
6564 // Note that we don't execute any pending app switches... we will
6565 // let those wait until either the timeout, or the next start
6566 // activity request.
6567 mAppSwitchesAllowedTime = 0;
6568 }
6569 }
6570
6571 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
6572 String name) {
6573 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
6574 return true;
6575 }
6576
6577 final int perm = checkComponentPermission(
6578 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08006579 callingUid, -1, true);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006580 if (perm == PackageManager.PERMISSION_GRANTED) {
6581 return true;
6582 }
6583
Joe Onorato8a9b2202010-02-26 18:56:32 -08006584 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006585 return false;
6586 }
6587
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006588 public void setDebugApp(String packageName, boolean waitForDebugger,
6589 boolean persistent) {
6590 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
6591 "setDebugApp()");
6592
6593 // Note that this is not really thread safe if there are multiple
6594 // callers into it at the same time, but that's not a situation we
6595 // care about.
6596 if (persistent) {
6597 final ContentResolver resolver = mContext.getContentResolver();
6598 Settings.System.putString(
6599 resolver, Settings.System.DEBUG_APP,
6600 packageName);
6601 Settings.System.putInt(
6602 resolver, Settings.System.WAIT_FOR_DEBUGGER,
6603 waitForDebugger ? 1 : 0);
6604 }
6605
6606 synchronized (this) {
6607 if (!persistent) {
6608 mOrigDebugApp = mDebugApp;
6609 mOrigWaitForDebugger = mWaitForDebugger;
6610 }
6611 mDebugApp = packageName;
6612 mWaitForDebugger = waitForDebugger;
6613 mDebugTransient = !persistent;
6614 if (packageName != null) {
6615 final long origId = Binder.clearCallingIdentity();
Christopher Tate3dacd842011-08-19 14:56:15 -07006616 forceStopPackageLocked(packageName, -1, false, false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006617 Binder.restoreCallingIdentity(origId);
6618 }
6619 }
6620 }
6621
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07006622 void setProfileApp(ApplicationInfo app, String processName, String profileFile,
6623 ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
6624 synchronized (this) {
6625 boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
6626 if (!isDebuggable) {
6627 if ((app.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
6628 throw new SecurityException("Process not debuggable: " + app.packageName);
6629 }
6630 }
6631 mProfileApp = processName;
6632 mProfileFile = profileFile;
6633 if (mProfileFd != null) {
6634 try {
6635 mProfileFd.close();
6636 } catch (IOException e) {
6637 }
6638 mProfileFd = null;
6639 }
6640 mProfileFd = profileFd;
6641 mProfileType = 0;
6642 mAutoStopProfiler = autoStopProfiler;
6643 }
6644 }
6645
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006646 public void setAlwaysFinish(boolean enabled) {
6647 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
6648 "setAlwaysFinish()");
6649
6650 Settings.System.putInt(
6651 mContext.getContentResolver(),
6652 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
6653
6654 synchronized (this) {
6655 mAlwaysFinishActivities = enabled;
6656 }
6657 }
6658
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006659 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006660 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006661 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006662 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006663 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006664 }
6665 }
6666
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08006667 public boolean isUserAMonkey() {
6668 // For now the fact that there is a controller implies
6669 // we have a monkey.
6670 synchronized (this) {
6671 return mController != null;
6672 }
6673 }
6674
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006675 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06006676 synchronized (this) {
6677 mWatchers.register(watcher);
6678 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006679 }
6680
6681 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06006682 synchronized (this) {
6683 mWatchers.unregister(watcher);
6684 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006685 }
6686
Jeff Sharkeya4620792011-05-20 15:29:23 -07006687 public void registerProcessObserver(IProcessObserver observer) {
6688 mProcessObservers.register(observer);
6689 }
6690
6691 public void unregisterProcessObserver(IProcessObserver observer) {
6692 mProcessObservers.unregister(observer);
6693 }
6694
Daniel Sandler69a48172010-06-23 16:29:36 -04006695 public void setImmersive(IBinder token, boolean immersive) {
6696 synchronized(this) {
Christopher Tate9ce685b2012-03-15 16:27:14 -07006697 final ActivityRecord r = mMainStack.isInStackLocked(token);
Dianne Hackbornce86ba82011-07-13 19:33:41 -07006698 if (r == null) {
Daniel Sandler69a48172010-06-23 16:29:36 -04006699 throw new IllegalArgumentException();
6700 }
Daniel Sandler69a48172010-06-23 16:29:36 -04006701 r.immersive = immersive;
Christopher Tate9ce685b2012-03-15 16:27:14 -07006702
6703 // update associated state if we're frontmost
6704 if (r == mMainStack.topRunningActivityLocked(null)) {
6705 long oldId = Binder.clearCallingIdentity();
6706 try {
6707 if (DEBUG_IMMERSIVE) {
6708 Slog.d(TAG, "Frontmost changed immersion: "+ r);
6709 }
6710 applyUpdateLockStateLocked(r);
6711 } finally {
6712 Binder.restoreCallingIdentity(oldId);
6713 }
6714 }
Daniel Sandler69a48172010-06-23 16:29:36 -04006715 }
6716 }
6717
6718 public boolean isImmersive(IBinder token) {
6719 synchronized (this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07006720 ActivityRecord r = mMainStack.isInStackLocked(token);
6721 if (r == null) {
Daniel Sandler69a48172010-06-23 16:29:36 -04006722 throw new IllegalArgumentException();
6723 }
Daniel Sandler69a48172010-06-23 16:29:36 -04006724 return r.immersive;
6725 }
6726 }
6727
6728 public boolean isTopActivityImmersive() {
6729 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006730 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Daniel Sandler69a48172010-06-23 16:29:36 -04006731 return (r != null) ? r.immersive : false;
6732 }
6733 }
6734
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006735 public final void enterSafeMode() {
6736 synchronized(this) {
6737 // It only makes sense to do this before the system is ready
6738 // and started launching other packages.
6739 if (!mSystemReady) {
6740 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006741 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006742 } catch (RemoteException e) {
6743 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006744 }
6745 }
6746 }
6747
Jeff Brownb09abc12011-01-13 21:08:27 -08006748 public final void showSafeModeOverlay() {
6749 View v = LayoutInflater.from(mContext).inflate(
6750 com.android.internal.R.layout.safe_mode, null);
6751 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
6752 lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
6753 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
6754 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
6755 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
6756 lp.format = v.getBackground().getOpacity();
6757 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
6758 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
6759 ((WindowManager)mContext.getSystemService(
6760 Context.WINDOW_SERVICE)).addView(v, lp);
6761 }
6762
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006763 public void noteWakeupAlarm(IIntentSender sender) {
6764 if (!(sender instanceof PendingIntentRecord)) {
6765 return;
6766 }
6767 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
6768 synchronized (stats) {
6769 if (mBatteryStatsService.isOnBattery()) {
6770 mBatteryStatsService.enforceCallingPermission();
6771 PendingIntentRecord rec = (PendingIntentRecord)sender;
6772 int MY_UID = Binder.getCallingUid();
6773 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
6774 BatteryStatsImpl.Uid.Pkg pkg =
6775 stats.getPackageStatsLocked(uid, rec.key.packageName);
6776 pkg.incWakeupsLocked();
6777 }
6778 }
6779 }
6780
Dianne Hackborn64825172011-03-02 21:32:58 -08006781 public boolean killPids(int[] pids, String pReason, boolean secure) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006782 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006783 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006784 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006785 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006786 // XXX Note: don't acquire main activity lock here, because the window
6787 // manager calls in with its locks held.
6788
6789 boolean killed = false;
6790 synchronized (mPidsSelfLocked) {
6791 int[] types = new int[pids.length];
6792 int worstType = 0;
6793 for (int i=0; i<pids.length; i++) {
6794 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6795 if (proc != null) {
6796 int type = proc.setAdj;
6797 types[i] = type;
6798 if (type > worstType) {
6799 worstType = type;
6800 }
6801 }
6802 }
6803
Dianne Hackborn64825172011-03-02 21:32:58 -08006804 // If the worst oom_adj is somewhere in the hidden proc LRU range,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006805 // then constrain it so we will kill all hidden procs.
Dianne Hackborne02c88a2011-10-28 13:58:15 -07006806 if (worstType < ProcessList.HIDDEN_APP_MAX_ADJ
6807 && worstType > ProcessList.HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn7d608422011-08-07 16:24:18 -07006808 worstType = ProcessList.HIDDEN_APP_MIN_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006809 }
Dianne Hackborn64825172011-03-02 21:32:58 -08006810
6811 // If this is not a secure call, don't let it kill processes that
6812 // are important.
Dianne Hackborne02c88a2011-10-28 13:58:15 -07006813 if (!secure && worstType < ProcessList.SERVICE_ADJ) {
6814 worstType = ProcessList.SERVICE_ADJ;
Dianne Hackborn64825172011-03-02 21:32:58 -08006815 }
6816
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006817 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006818 for (int i=0; i<pids.length; i++) {
6819 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6820 if (proc == null) {
6821 continue;
6822 }
6823 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006824 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07006825 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006826 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
6827 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006828 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006829 proc.killedBackground = true;
6830 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006831 }
6832 }
6833 }
6834 return killed;
6835 }
6836
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006837 public final void startRunning(String pkg, String cls, String action,
6838 String data) {
6839 synchronized(this) {
6840 if (mStartRunning) {
6841 return;
6842 }
6843 mStartRunning = true;
6844 mTopComponent = pkg != null && cls != null
6845 ? new ComponentName(pkg, cls) : null;
6846 mTopAction = action != null ? action : Intent.ACTION_MAIN;
6847 mTopData = data;
6848 if (!mSystemReady) {
6849 return;
6850 }
6851 }
6852
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006853 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006854 }
6855
6856 private void retrieveSettings() {
6857 final ContentResolver resolver = mContext.getContentResolver();
6858 String debugApp = Settings.System.getString(
6859 resolver, Settings.System.DEBUG_APP);
6860 boolean waitForDebugger = Settings.System.getInt(
6861 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
6862 boolean alwaysFinishActivities = Settings.System.getInt(
6863 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
6864
6865 Configuration configuration = new Configuration();
6866 Settings.System.getConfiguration(resolver, configuration);
6867
6868 synchronized (this) {
6869 mDebugApp = mOrigDebugApp = debugApp;
6870 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
6871 mAlwaysFinishActivities = alwaysFinishActivities;
6872 // This happens before any activities are started, so we can
6873 // change mConfiguration in-place.
Dianne Hackborn813075a62011-11-14 17:45:19 -08006874 updateConfigurationLocked(configuration, null, false, true);
Joe Onorato8a9b2202010-02-26 18:56:32 -08006875 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006876 }
6877 }
6878
6879 public boolean testIsSystemReady() {
6880 // no need to synchronize(this) just to read & return the value
6881 return mSystemReady;
6882 }
6883
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006884 private static File getCalledPreBootReceiversFile() {
6885 File dataDir = Environment.getDataDirectory();
6886 File systemDir = new File(dataDir, "system");
6887 File fname = new File(systemDir, "called_pre_boots.dat");
6888 return fname;
6889 }
Dianne Hackborn661cd522011-08-22 00:26:20 -07006890
6891 static final int LAST_DONE_VERSION = 10000;
6892
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006893 private static ArrayList<ComponentName> readLastDonePreBootReceivers() {
6894 ArrayList<ComponentName> lastDoneReceivers = new ArrayList<ComponentName>();
6895 File file = getCalledPreBootReceiversFile();
6896 FileInputStream fis = null;
6897 try {
6898 fis = new FileInputStream(file);
6899 DataInputStream dis = new DataInputStream(new BufferedInputStream(fis, 2048));
Dianne Hackborn661cd522011-08-22 00:26:20 -07006900 int fvers = dis.readInt();
6901 if (fvers == LAST_DONE_VERSION) {
6902 String vers = dis.readUTF();
6903 String codename = dis.readUTF();
6904 String build = dis.readUTF();
6905 if (android.os.Build.VERSION.RELEASE.equals(vers)
6906 && android.os.Build.VERSION.CODENAME.equals(codename)
6907 && android.os.Build.VERSION.INCREMENTAL.equals(build)) {
6908 int num = dis.readInt();
6909 while (num > 0) {
6910 num--;
6911 String pkg = dis.readUTF();
6912 String cls = dis.readUTF();
6913 lastDoneReceivers.add(new ComponentName(pkg, cls));
6914 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006915 }
6916 }
6917 } catch (FileNotFoundException e) {
6918 } catch (IOException e) {
6919 Slog.w(TAG, "Failure reading last done pre-boot receivers", e);
6920 } finally {
6921 if (fis != null) {
6922 try {
6923 fis.close();
6924 } catch (IOException e) {
6925 }
6926 }
6927 }
6928 return lastDoneReceivers;
6929 }
6930
6931 private static void writeLastDonePreBootReceivers(ArrayList<ComponentName> list) {
6932 File file = getCalledPreBootReceiversFile();
6933 FileOutputStream fos = null;
6934 DataOutputStream dos = null;
6935 try {
6936 Slog.i(TAG, "Writing new set of last done pre-boot receivers...");
6937 fos = new FileOutputStream(file);
6938 dos = new DataOutputStream(new BufferedOutputStream(fos, 2048));
Dianne Hackborn661cd522011-08-22 00:26:20 -07006939 dos.writeInt(LAST_DONE_VERSION);
6940 dos.writeUTF(android.os.Build.VERSION.RELEASE);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006941 dos.writeUTF(android.os.Build.VERSION.CODENAME);
Dianne Hackborn661cd522011-08-22 00:26:20 -07006942 dos.writeUTF(android.os.Build.VERSION.INCREMENTAL);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006943 dos.writeInt(list.size());
6944 for (int i=0; i<list.size(); i++) {
6945 dos.writeUTF(list.get(i).getPackageName());
6946 dos.writeUTF(list.get(i).getClassName());
6947 }
6948 } catch (IOException e) {
6949 Slog.w(TAG, "Failure writing last done pre-boot receivers", e);
6950 file.delete();
6951 } finally {
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07006952 FileUtils.sync(fos);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006953 if (dos != null) {
6954 try {
6955 dos.close();
6956 } catch (IOException e) {
6957 // TODO Auto-generated catch block
6958 e.printStackTrace();
6959 }
6960 }
6961 }
6962 }
6963
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006964 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006965 synchronized(this) {
6966 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006967 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006968 return;
6969 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006970
6971 // Check to see if there are any update receivers to run.
6972 if (!mDidUpdate) {
6973 if (mWaitingUpdate) {
6974 return;
6975 }
6976 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
6977 List<ResolveInfo> ris = null;
6978 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006979 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006980 intent, null, 0);
6981 } catch (RemoteException e) {
6982 }
6983 if (ris != null) {
6984 for (int i=ris.size()-1; i>=0; i--) {
6985 if ((ris.get(i).activityInfo.applicationInfo.flags
6986 &ApplicationInfo.FLAG_SYSTEM) == 0) {
6987 ris.remove(i);
6988 }
6989 }
6990 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006991
6992 ArrayList<ComponentName> lastDoneReceivers = readLastDonePreBootReceivers();
6993
6994 final ArrayList<ComponentName> doneReceivers = new ArrayList<ComponentName>();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006995 for (int i=0; i<ris.size(); i++) {
6996 ActivityInfo ai = ris.get(i).activityInfo;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006997 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6998 if (lastDoneReceivers.contains(comp)) {
6999 ris.remove(i);
7000 i--;
7001 }
7002 }
Dianne Hackborn29aae6f2011-08-18 18:30:09 -07007003
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007004 for (int i=0; i<ris.size(); i++) {
7005 ActivityInfo ai = ris.get(i).activityInfo;
7006 ComponentName comp = new ComponentName(ai.packageName, ai.name);
7007 doneReceivers.add(comp);
7008 intent.setComponent(comp);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007009 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08007010 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007011 finisher = new IIntentReceiver.Stub() {
7012 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07007013 String data, Bundle extras, boolean ordered,
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07007014 boolean sticky) {
7015 // The raw IIntentReceiver interface is called
7016 // with the AM lock held, so redispatch to
7017 // execute our code without the lock.
7018 mHandler.post(new Runnable() {
7019 public void run() {
7020 synchronized (ActivityManagerService.this) {
7021 mDidUpdate = true;
7022 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007023 writeLastDonePreBootReceivers(doneReceivers);
Dianne Hackborn661cd522011-08-22 00:26:20 -07007024 showBootMessage(mContext.getText(
7025 R.string.android_upgrading_complete),
7026 false);
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07007027 systemReady(goingCallback);
7028 }
7029 });
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007030 }
7031 };
7032 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007033 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007034 broadcastIntentLocked(null, null, intent, null, finisher,
7035 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08007036 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007037 mWaitingUpdate = true;
7038 }
7039 }
7040 }
7041 if (mWaitingUpdate) {
7042 return;
7043 }
7044 mDidUpdate = true;
7045 }
7046
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007047 mSystemReady = true;
7048 if (!mStartRunning) {
7049 return;
7050 }
7051 }
7052
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007053 ArrayList<ProcessRecord> procsToKill = null;
7054 synchronized(mPidsSelfLocked) {
7055 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
7056 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
7057 if (!isAllowedWhileBooting(proc.info)){
7058 if (procsToKill == null) {
7059 procsToKill = new ArrayList<ProcessRecord>();
7060 }
7061 procsToKill.add(proc);
7062 }
7063 }
7064 }
7065
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007066 synchronized(this) {
7067 if (procsToKill != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007068 for (int i=procsToKill.size()-1; i>=0; i--) {
7069 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007070 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08007071 removeProcessLocked(proc, true, false, "system update done");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007072 }
7073 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007074
7075 // Now that we have cleaned up any update processes, we
7076 // are ready to start launching real processes and know that
7077 // we won't trample on them any more.
7078 mProcessesReady = true;
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007079 }
7080
Joe Onorato8a9b2202010-02-26 18:56:32 -08007081 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08007082 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007083 SystemClock.uptimeMillis());
7084
7085 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007086 // Make sure we have no pre-ready processes sitting around.
7087
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007088 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
7089 ResolveInfo ri = mContext.getPackageManager()
7090 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07007091 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007092 CharSequence errorMsg = null;
7093 if (ri != null) {
7094 ActivityInfo ai = ri.activityInfo;
7095 ApplicationInfo app = ai.applicationInfo;
7096 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
7097 mTopAction = Intent.ACTION_FACTORY_TEST;
7098 mTopData = null;
7099 mTopComponent = new ComponentName(app.packageName,
7100 ai.name);
7101 } else {
7102 errorMsg = mContext.getResources().getText(
7103 com.android.internal.R.string.factorytest_not_system);
7104 }
7105 } else {
7106 errorMsg = mContext.getResources().getText(
7107 com.android.internal.R.string.factorytest_no_action);
7108 }
7109 if (errorMsg != null) {
7110 mTopAction = null;
7111 mTopData = null;
7112 mTopComponent = null;
7113 Message msg = Message.obtain();
7114 msg.what = SHOW_FACTORY_ERROR_MSG;
7115 msg.getData().putCharSequence("msg", errorMsg);
7116 mHandler.sendMessage(msg);
7117 }
7118 }
7119 }
7120
7121 retrieveSettings();
7122
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07007123 if (goingCallback != null) goingCallback.run();
7124
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007125 synchronized (this) {
7126 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
7127 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007128 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07007129 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007130 if (apps != null) {
7131 int N = apps.size();
7132 int i;
7133 for (i=0; i<N; i++) {
7134 ApplicationInfo info
7135 = (ApplicationInfo)apps.get(i);
7136 if (info != null &&
7137 !info.packageName.equals("android")) {
7138 addAppLocked(info);
7139 }
7140 }
7141 }
7142 } catch (RemoteException ex) {
7143 // pm is in same process, this will never happen.
7144 }
7145 }
7146
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007147 // Start up initial activity.
7148 mBooting = true;
7149
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007150 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007151 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007152 Message msg = Message.obtain();
7153 msg.what = SHOW_UID_ERROR_MSG;
7154 mHandler.sendMessage(msg);
7155 }
7156 } catch (RemoteException e) {
7157 }
7158
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007159 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007160 }
7161 }
7162
Dan Egnorb7f03672009-12-09 16:22:32 -08007163 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08007164 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007165 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08007166 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08007167 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007168 startAppProblemLocked(app);
7169 app.stopFreezingAllLocked();
7170 return handleAppCrashLocked(app);
7171 }
7172
Dan Egnorb7f03672009-12-09 16:22:32 -08007173 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08007174 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007175 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08007176 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08007177 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
7178 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007179 startAppProblemLocked(app);
7180 app.stopFreezingAllLocked();
7181 }
7182
7183 /**
7184 * Generate a process error record, suitable for attachment to a ProcessRecord.
7185 *
7186 * @param app The ProcessRecord in which the error occurred.
7187 * @param condition Crashing, Application Not Responding, etc. Values are defined in
7188 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08007189 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007190 * @param shortMsg Short message describing the crash.
7191 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08007192 * @param stackTrace Full crash stack trace, may be null.
7193 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007194 * @return Returns a fully-formed AppErrorStateInfo record.
7195 */
7196 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08007197 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007198 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08007199
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007200 report.condition = condition;
7201 report.processName = app.processName;
7202 report.pid = app.pid;
7203 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08007204 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007205 report.shortMsg = shortMsg;
7206 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08007207 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007208
7209 return report;
7210 }
7211
Dan Egnor42471dd2010-01-07 17:25:22 -08007212 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007213 synchronized (this) {
7214 app.crashing = false;
7215 app.crashingReport = null;
7216 app.notResponding = false;
7217 app.notRespondingReport = null;
7218 if (app.anrDialog == fromDialog) {
7219 app.anrDialog = null;
7220 }
7221 if (app.waitDialog == fromDialog) {
7222 app.waitDialog = null;
7223 }
7224 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08007225 handleAppCrashLocked(app);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07007226 Slog.i(ActivityManagerService.TAG, "Killing " + app + ": user's request");
Dianne Hackborn8633e682010-04-22 16:03:41 -07007227 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
7228 app.processName, app.setAdj, "user's request after error");
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07007229 Process.killProcessQuiet(app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007230 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007231 }
7232 }
Dan Egnor42471dd2010-01-07 17:25:22 -08007233
Dan Egnorb7f03672009-12-09 16:22:32 -08007234 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007235 long now = SystemClock.uptimeMillis();
7236
7237 Long crashTime = mProcessCrashTimes.get(app.info.processName,
7238 app.info.uid);
Dianne Hackborn7d608422011-08-07 16:24:18 -07007239 if (crashTime != null && now < crashTime+ProcessList.MIN_CRASH_INTERVAL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007240 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08007241 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007242 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08007243 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007244 app.info.processName, app.info.uid);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007245 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
7246 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007247 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007248 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007249 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007250 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007251 }
7252 }
7253 if (!app.persistent) {
7254 // We don't want to start this process again until the user
7255 // explicitly does so... but for persistent process, we really
7256 // need to keep it running. If a persistent process is actually
7257 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08007258 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007259 app.info.processName);
7260 mBadProcesses.put(app.info.processName, app.info.uid, now);
7261 app.bad = true;
7262 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
7263 app.removed = true;
Dianne Hackborn130b0d22011-07-26 22:07:48 -07007264 // Don't let services in this process be restarted and potentially
7265 // annoy the user repeatedly. Unless it is persistent, since those
7266 // processes run critical code.
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08007267 removeProcessLocked(app, false, false, "crash");
Dianne Hackborncb44d962011-03-10 17:02:27 -08007268 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007269 return false;
7270 }
Dianne Hackborncb44d962011-03-10 17:02:27 -08007271 mMainStack.resumeTopActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07007272 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007273 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Kevin Hester-Chow2d72be22012-03-05 08:01:00 -08007274 if (r != null && r.app == app) {
Dianne Hackbornf83c5552010-03-31 22:19:32 -07007275 // If the top running activity is from this crashing
7276 // process, then terminate it to avoid getting in a loop.
7277 Slog.w(TAG, " Force finishing activity "
7278 + r.intent.getComponent().flattenToShortString());
Dianne Hackbornbe707852011-11-11 14:32:10 -08007279 int index = mMainStack.indexOfActivityLocked(r);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007280 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07007281 Activity.RESULT_CANCELED, null, "crashed");
Dianne Hackborn070783f2010-12-29 16:46:28 -08007282 // Also terminate any activities below it that aren't yet
Dianne Hackbornf83c5552010-03-31 22:19:32 -07007283 // stopped, to avoid a situation where one will get
7284 // re-start our crashing activity once it gets resumed again.
7285 index--;
7286 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007287 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07007288 if (r.state == ActivityState.RESUMED
7289 || r.state == ActivityState.PAUSING
7290 || r.state == ActivityState.PAUSED) {
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -08007291 if (!r.isHomeActivity || mHomeProcess != r.app) {
Dianne Hackbornf83c5552010-03-31 22:19:32 -07007292 Slog.w(TAG, " Force finishing activity "
7293 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007294 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07007295 Activity.RESULT_CANCELED, null, "crashed");
7296 }
7297 }
7298 }
7299 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007300 }
7301
7302 // Bump up the crash count of any services currently running in the proc.
7303 if (app.services.size() != 0) {
7304 // Any services running in the application need to be placed
7305 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07007306 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007307 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007308 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007309 sr.crashCount++;
7310 }
7311 }
Mattias Larssona4fd0072010-06-22 22:37:03 +02007312
7313 // If the crashing process is what we consider to be the "home process" and it has been
7314 // replaced by a third-party app, clear the package preferred activities from packages
7315 // with a home activity running in the process to prevent a repeatedly crashing app
7316 // from blocking the user to manually clear the list.
7317 if (app == mHomeProcess && mHomeProcess.activities.size() > 0
7318 && (mHomeProcess.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
7319 Iterator it = mHomeProcess.activities.iterator();
7320 while (it.hasNext()) {
Jean-Baptiste Queru5ea89f72010-07-30 09:30:31 -07007321 ActivityRecord r = (ActivityRecord)it.next();
Mattias Larssona4fd0072010-06-22 22:37:03 +02007322 if (r.isHomeActivity) {
7323 Log.i(TAG, "Clearing package preferred activities from " + r.packageName);
7324 try {
7325 ActivityThread.getPackageManager()
7326 .clearPackagePreferredActivities(r.packageName);
7327 } catch (RemoteException c) {
7328 // pm is in same process, this will never happen.
7329 }
7330 }
7331 }
7332 }
7333
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007334 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
7335 return true;
7336 }
7337
7338 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08007339 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
7340 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007341 skipCurrentReceiverLocked(app);
7342 }
7343
7344 void skipCurrentReceiverLocked(ProcessRecord app) {
7345 boolean reschedule = false;
7346 BroadcastRecord r = app.curReceiver;
7347 if (r != null) {
7348 // The current broadcast is waiting for this app's receiver
7349 // to be finished. Looks like that's not going to happen, so
7350 // let the broadcast continue.
Jeff Brown4d94a762010-09-23 11:33:28 -07007351 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007352 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
7353 r.resultExtras, r.resultAbort, true);
7354 reschedule = true;
7355 }
7356 r = mPendingBroadcast;
7357 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007358 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007359 "skip & discard pending app " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -07007360 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007361 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
7362 r.resultExtras, r.resultAbort, true);
7363 reschedule = true;
7364 }
7365 if (reschedule) {
7366 scheduleBroadcastsLocked();
7367 }
7368 }
7369
Dan Egnor60d87622009-12-16 16:32:58 -08007370 /**
7371 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
7372 * The application process will exit immediately after this call returns.
7373 * @param app object of the crashing app, null for the system server
7374 * @param crashInfo describing the exception
7375 */
7376 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
Dianne Hackborncb44d962011-03-10 17:02:27 -08007377 ProcessRecord r = findAppProcess(app, "Crash");
Jeff Sharkeya353d262011-10-28 11:12:06 -07007378 final String processName = app == null ? "system_server"
7379 : (r == null ? "unknown" : r.processName);
Dan Egnor60d87622009-12-16 16:32:58 -08007380
7381 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
Jeff Sharkeya353d262011-10-28 11:12:06 -07007382 processName,
Dan Egnor2780e732010-01-22 14:47:35 -08007383 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08007384 crashInfo.exceptionClassName,
7385 crashInfo.exceptionMessage,
7386 crashInfo.throwFileName,
7387 crashInfo.throwLineNumber);
7388
Jeff Sharkeya353d262011-10-28 11:12:06 -07007389 addErrorToDropBox("crash", r, processName, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08007390
7391 crashApplication(r, crashInfo);
7392 }
7393
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07007394 public void handleApplicationStrictModeViolation(
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007395 IBinder app,
7396 int violationMask,
7397 StrictMode.ViolationInfo info) {
Dianne Hackborncb44d962011-03-10 17:02:27 -08007398 ProcessRecord r = findAppProcess(app, "StrictMode");
7399 if (r == null) {
7400 return;
7401 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07007402
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07007403 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -08007404 Integer stackFingerprint = info.hashCode();
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07007405 boolean logIt = true;
7406 synchronized (mAlreadyLoggedViolatedStacks) {
7407 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
7408 logIt = false;
7409 // TODO: sub-sample into EventLog for these, with
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007410 // the info.durationMillis? Then we'd get
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07007411 // the relative pain numbers, without logging all
7412 // the stack traces repeatedly. We'd want to do
7413 // likewise in the client code, which also does
7414 // dup suppression, before the Binder call.
7415 } else {
7416 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
7417 mAlreadyLoggedViolatedStacks.clear();
7418 }
7419 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
7420 }
7421 }
7422 if (logIt) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007423 logStrictModeViolationToDropBox(r, info);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07007424 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07007425 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07007426
7427 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
7428 AppErrorResult result = new AppErrorResult();
7429 synchronized (this) {
7430 final long origId = Binder.clearCallingIdentity();
7431
7432 Message msg = Message.obtain();
7433 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
7434 HashMap<String, Object> data = new HashMap<String, Object>();
7435 data.put("result", result);
7436 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07007437 data.put("violationMask", violationMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007438 data.put("info", info);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07007439 msg.obj = data;
7440 mHandler.sendMessage(msg);
7441
7442 Binder.restoreCallingIdentity(origId);
7443 }
7444 int res = result.get();
Dianne Hackbornb424b632010-08-18 15:59:05 -07007445 Slog.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07007446 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07007447 }
7448
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007449 // Depending on the policy in effect, there could be a bunch of
7450 // these in quick succession so we try to batch these together to
7451 // minimize disk writes, number of dropbox entries, and maximize
7452 // compression, by having more fewer, larger records.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007453 private void logStrictModeViolationToDropBox(
7454 ProcessRecord process,
7455 StrictMode.ViolationInfo info) {
7456 if (info == null) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007457 return;
7458 }
7459 final boolean isSystemApp = process == null ||
7460 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
7461 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
Jeff Sharkeya353d262011-10-28 11:12:06 -07007462 final String processName = process == null ? "unknown" : process.processName;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007463 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
7464 final DropBoxManager dbox = (DropBoxManager)
7465 mContext.getSystemService(Context.DROPBOX_SERVICE);
7466
7467 // Exit early if the dropbox isn't configured to accept this report type.
7468 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
7469
7470 boolean bufferWasEmpty;
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007471 boolean needsFlush;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007472 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
7473 synchronized (sb) {
7474 bufferWasEmpty = sb.length() == 0;
Jeff Sharkeya353d262011-10-28 11:12:06 -07007475 appendDropBoxProcessHeaders(process, processName, sb);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007476 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
7477 sb.append("System-App: ").append(isSystemApp).append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007478 sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
7479 if (info.violationNumThisLoop != 0) {
7480 sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
7481 }
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07007482 if (info.numAnimationsRunning != 0) {
7483 sb.append("Animations-Running: ").append(info.numAnimationsRunning).append("\n");
7484 }
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07007485 if (info.broadcastIntentAction != null) {
7486 sb.append("Broadcast-Intent-Action: ").append(info.broadcastIntentAction).append("\n");
7487 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08007488 if (info.durationMillis != -1) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007489 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007490 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08007491 if (info.numInstances != -1) {
7492 sb.append("Instance-Count: ").append(info.numInstances).append("\n");
7493 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08007494 if (info.tags != null) {
7495 for (String tag : info.tags) {
7496 sb.append("Span-Tag: ").append(tag).append("\n");
7497 }
7498 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007499 sb.append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007500 if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
7501 sb.append(info.crashInfo.stackTrace);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007502 }
7503 sb.append("\n");
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007504
7505 // Only buffer up to ~64k. Various logging bits truncate
7506 // things at 128k.
7507 needsFlush = (sb.length() > 64 * 1024);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007508 }
7509
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007510 // Flush immediately if the buffer's grown too large, or this
7511 // is a non-system app. Non-system apps are isolated with a
7512 // different tag & policy and not batched.
7513 //
7514 // Batching is useful during internal testing with
7515 // StrictMode settings turned up high. Without batching,
7516 // thousands of separate files could be created on boot.
7517 if (!isSystemApp || needsFlush) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007518 new Thread("Error dump: " + dropboxTag) {
7519 @Override
7520 public void run() {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007521 String report;
7522 synchronized (sb) {
7523 report = sb.toString();
7524 sb.delete(0, sb.length());
7525 sb.trimToSize();
7526 }
7527 if (report.length() != 0) {
7528 dbox.addText(dropboxTag, report);
7529 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007530 }
7531 }.start();
7532 return;
7533 }
7534
7535 // System app batching:
7536 if (!bufferWasEmpty) {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007537 // An existing dropbox-writing thread is outstanding, so
7538 // we don't need to start it up. The existing thread will
7539 // catch the buffer appends we just did.
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007540 return;
7541 }
7542
7543 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
7544 // (After this point, we shouldn't access AMS internal data structures.)
7545 new Thread("Error dump: " + dropboxTag) {
7546 @Override
7547 public void run() {
7548 // 5 second sleep to let stacks arrive and be batched together
7549 try {
7550 Thread.sleep(5000); // 5 seconds
7551 } catch (InterruptedException e) {}
7552
7553 String errorReport;
7554 synchronized (mStrictModeBuffer) {
7555 errorReport = mStrictModeBuffer.toString();
7556 if (errorReport.length() == 0) {
7557 return;
7558 }
7559 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
7560 mStrictModeBuffer.trimToSize();
7561 }
7562 dbox.addText(dropboxTag, errorReport);
7563 }
7564 }.start();
7565 }
7566
Dan Egnor60d87622009-12-16 16:32:58 -08007567 /**
7568 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
7569 * @param app object of the crashing app, null for the system server
7570 * @param tag reported by the caller
7571 * @param crashInfo describing the context of the error
7572 * @return true if the process should exit immediately (WTF is fatal)
7573 */
7574 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08007575 ApplicationErrorReport.CrashInfo crashInfo) {
Dianne Hackborncb44d962011-03-10 17:02:27 -08007576 ProcessRecord r = findAppProcess(app, "WTF");
Jeff Sharkeya353d262011-10-28 11:12:06 -07007577 final String processName = app == null ? "system_server"
7578 : (r == null ? "unknown" : r.processName);
Dan Egnor60d87622009-12-16 16:32:58 -08007579
7580 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
Jeff Sharkeya353d262011-10-28 11:12:06 -07007581 processName,
Dan Egnor2780e732010-01-22 14:47:35 -08007582 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08007583 tag, crashInfo.exceptionMessage);
7584
Jeff Sharkeya353d262011-10-28 11:12:06 -07007585 addErrorToDropBox("wtf", r, processName, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08007586
Dianne Hackborn1ab43772011-03-15 14:38:02 -07007587 if (r != null && r.pid != Process.myPid() &&
7588 Settings.Secure.getInt(mContext.getContentResolver(),
7589 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08007590 crashApplication(r, crashInfo);
7591 return true;
7592 } else {
7593 return false;
7594 }
7595 }
7596
7597 /**
7598 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
7599 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
7600 */
Dianne Hackborncb44d962011-03-10 17:02:27 -08007601 private ProcessRecord findAppProcess(IBinder app, String reason) {
Dan Egnor60d87622009-12-16 16:32:58 -08007602 if (app == null) {
7603 return null;
7604 }
7605
7606 synchronized (this) {
7607 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
7608 final int NA = apps.size();
7609 for (int ia=0; ia<NA; ia++) {
7610 ProcessRecord p = apps.valueAt(ia);
7611 if (p.thread != null && p.thread.asBinder() == app) {
7612 return p;
7613 }
7614 }
7615 }
7616
Dianne Hackborncb44d962011-03-10 17:02:27 -08007617 Slog.w(TAG, "Can't find mystery application for " + reason
7618 + " from pid=" + Binder.getCallingPid()
7619 + " uid=" + Binder.getCallingUid() + ": " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08007620 return null;
7621 }
7622 }
7623
7624 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007625 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
7626 * to append various headers to the dropbox log text.
Dan Egnor60d87622009-12-16 16:32:58 -08007627 */
Jeff Sharkeya353d262011-10-28 11:12:06 -07007628 private void appendDropBoxProcessHeaders(ProcessRecord process, String processName,
7629 StringBuilder sb) {
Vairavan Srinivasan68a4e0a2011-02-14 20:45:59 -08007630 // Watchdog thread ends up invoking this function (with
7631 // a null ProcessRecord) to add the stack file to dropbox.
7632 // Do not acquire a lock on this (am) in such cases, as it
7633 // could cause a potential deadlock, if and when watchdog
7634 // is invoked due to unavailability of lock on am and it
7635 // would prevent watchdog from killing system_server.
7636 if (process == null) {
Jeff Sharkeya353d262011-10-28 11:12:06 -07007637 sb.append("Process: ").append(processName).append("\n");
Vairavan Srinivasan68a4e0a2011-02-14 20:45:59 -08007638 return;
7639 }
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07007640 // Note: ProcessRecord 'process' is guarded by the service
7641 // instance. (notably process.pkgList, which could otherwise change
7642 // concurrently during execution of this method)
7643 synchronized (this) {
Jeff Sharkeya353d262011-10-28 11:12:06 -07007644 sb.append("Process: ").append(processName).append("\n");
Dan Egnora455d192010-03-12 08:52:28 -08007645 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007646 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08007647 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
7648 for (String pkg : process.pkgList) {
7649 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08007650 try {
Dan Egnora455d192010-03-12 08:52:28 -08007651 PackageInfo pi = pm.getPackageInfo(pkg, 0);
7652 if (pi != null) {
7653 sb.append(" v").append(pi.versionCode);
7654 if (pi.versionName != null) {
7655 sb.append(" (").append(pi.versionName).append(")");
7656 }
7657 }
7658 } catch (RemoteException e) {
7659 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08007660 }
Dan Egnora455d192010-03-12 08:52:28 -08007661 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08007662 }
Dan Egnora455d192010-03-12 08:52:28 -08007663 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007664 }
7665
7666 private static String processClass(ProcessRecord process) {
7667 if (process == null || process.pid == MY_PID) {
7668 return "system_server";
7669 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
7670 return "system_app";
7671 } else {
7672 return "data_app";
7673 }
7674 }
7675
7676 /**
7677 * Write a description of an error (crash, WTF, ANR) to the drop box.
7678 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
7679 * @param process which caused the error, null means the system server
7680 * @param activity which triggered the error, null if unknown
7681 * @param parent activity related to the error, null if unknown
7682 * @param subject line related to the error, null if absent
7683 * @param report in long form describing the error, null if absent
7684 * @param logFile to include in the report, null if none
7685 * @param crashInfo giving an application stack trace, null if absent
7686 */
7687 public void addErrorToDropBox(String eventType,
Jeff Sharkeya353d262011-10-28 11:12:06 -07007688 ProcessRecord process, String processName, ActivityRecord activity,
7689 ActivityRecord parent, String subject,
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007690 final String report, final File logFile,
7691 final ApplicationErrorReport.CrashInfo crashInfo) {
7692 // NOTE -- this must never acquire the ActivityManagerService lock,
7693 // otherwise the watchdog may be prevented from resetting the system.
7694
7695 final String dropboxTag = processClass(process) + "_" + eventType;
7696 final DropBoxManager dbox = (DropBoxManager)
7697 mContext.getSystemService(Context.DROPBOX_SERVICE);
7698
7699 // Exit early if the dropbox isn't configured to accept this report type.
7700 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
7701
7702 final StringBuilder sb = new StringBuilder(1024);
Jeff Sharkeya353d262011-10-28 11:12:06 -07007703 appendDropBoxProcessHeaders(process, processName, sb);
Dan Egnora455d192010-03-12 08:52:28 -08007704 if (activity != null) {
7705 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
7706 }
7707 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
7708 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
7709 }
7710 if (parent != null && parent != activity) {
7711 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
7712 }
7713 if (subject != null) {
7714 sb.append("Subject: ").append(subject).append("\n");
7715 }
7716 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
Christian Lindeberg03d2ca62010-09-28 14:52:20 +02007717 if (Debug.isDebuggerConnected()) {
7718 sb.append("Debugger: Connected\n");
7719 }
Dan Egnora455d192010-03-12 08:52:28 -08007720 sb.append("\n");
7721
7722 // Do the rest in a worker thread to avoid blocking the caller on I/O
7723 // (After this point, we shouldn't access AMS internal data structures.)
7724 Thread worker = new Thread("Error dump: " + dropboxTag) {
7725 @Override
7726 public void run() {
7727 if (report != null) {
7728 sb.append(report);
7729 }
7730 if (logFile != null) {
7731 try {
7732 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
7733 } catch (IOException e) {
7734 Slog.e(TAG, "Error reading " + logFile, e);
7735 }
7736 }
7737 if (crashInfo != null && crashInfo.stackTrace != null) {
7738 sb.append(crashInfo.stackTrace);
7739 }
7740
7741 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
7742 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
7743 if (lines > 0) {
7744 sb.append("\n");
7745
7746 // Merge several logcat streams, and take the last N lines
7747 InputStreamReader input = null;
7748 try {
7749 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
7750 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
7751 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
7752
7753 try { logcat.getOutputStream().close(); } catch (IOException e) {}
7754 try { logcat.getErrorStream().close(); } catch (IOException e) {}
7755 input = new InputStreamReader(logcat.getInputStream());
7756
7757 int num;
7758 char[] buf = new char[8192];
7759 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
7760 } catch (IOException e) {
7761 Slog.e(TAG, "Error running logcat", e);
7762 } finally {
7763 if (input != null) try { input.close(); } catch (IOException e) {}
7764 }
7765 }
7766
7767 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08007768 }
Dan Egnora455d192010-03-12 08:52:28 -08007769 };
7770
7771 if (process == null || process.pid == MY_PID) {
7772 worker.run(); // We may be about to die -- need to run this synchronously
7773 } else {
7774 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08007775 }
7776 }
7777
7778 /**
7779 * Bring up the "unexpected error" dialog box for a crashing app.
7780 * Deal with edge cases (intercepts from instrumented applications,
7781 * ActivityController, error intent receivers, that sort of thing).
7782 * @param r the application crashing
7783 * @param crashInfo describing the failure
7784 */
7785 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007786 long timeMillis = System.currentTimeMillis();
7787 String shortMsg = crashInfo.exceptionClassName;
7788 String longMsg = crashInfo.exceptionMessage;
7789 String stackTrace = crashInfo.stackTrace;
7790 if (shortMsg != null && longMsg != null) {
7791 longMsg = shortMsg + ": " + longMsg;
7792 } else if (shortMsg != null) {
7793 longMsg = shortMsg;
7794 }
7795
Dan Egnor60d87622009-12-16 16:32:58 -08007796 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007797 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007798 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007799 try {
7800 String name = r != null ? r.processName : null;
7801 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08007802 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08007803 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007804 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007805 + " at watcher's request");
7806 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08007807 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007808 }
7809 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007810 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007811 }
7812 }
7813
7814 final long origId = Binder.clearCallingIdentity();
7815
7816 // If this process is running instrumentation, finish it.
7817 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007818 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007819 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08007820 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
7821 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007822 Bundle info = new Bundle();
7823 info.putString("shortMsg", shortMsg);
7824 info.putString("longMsg", longMsg);
7825 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
7826 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007827 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007828 }
7829
Dan Egnor60d87622009-12-16 16:32:58 -08007830 // If we can't identify the process or it's already exceeded its crash quota,
7831 // quit right away without showing a crash dialog.
7832 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007833 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007834 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007835 }
7836
7837 Message msg = Message.obtain();
7838 msg.what = SHOW_ERROR_MSG;
7839 HashMap data = new HashMap();
7840 data.put("result", result);
7841 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007842 msg.obj = data;
7843 mHandler.sendMessage(msg);
7844
7845 Binder.restoreCallingIdentity(origId);
7846 }
7847
7848 int res = result.get();
7849
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007850 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007851 synchronized (this) {
7852 if (r != null) {
7853 mProcessCrashTimes.put(r.info.processName, r.info.uid,
7854 SystemClock.uptimeMillis());
7855 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007856 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007857 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007858 }
7859 }
7860
7861 if (appErrorIntent != null) {
7862 try {
7863 mContext.startActivity(appErrorIntent);
7864 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007865 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007866 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007867 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007868 }
Dan Egnorb7f03672009-12-09 16:22:32 -08007869
7870 Intent createAppErrorIntentLocked(ProcessRecord r,
7871 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
7872 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007873 if (report == null) {
7874 return null;
7875 }
7876 Intent result = new Intent(Intent.ACTION_APP_ERROR);
7877 result.setComponent(r.errorReportReceiver);
7878 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
7879 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
7880 return result;
7881 }
7882
Dan Egnorb7f03672009-12-09 16:22:32 -08007883 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
7884 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007885 if (r.errorReportReceiver == null) {
7886 return null;
7887 }
7888
7889 if (!r.crashing && !r.notResponding) {
7890 return null;
7891 }
7892
Dan Egnorb7f03672009-12-09 16:22:32 -08007893 ApplicationErrorReport report = new ApplicationErrorReport();
7894 report.packageName = r.info.packageName;
7895 report.installerPackageName = r.errorReportReceiver.getPackageName();
7896 report.processName = r.processName;
7897 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01007898 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007899
Dan Egnorb7f03672009-12-09 16:22:32 -08007900 if (r.crashing) {
7901 report.type = ApplicationErrorReport.TYPE_CRASH;
7902 report.crashInfo = crashInfo;
7903 } else if (r.notResponding) {
7904 report.type = ApplicationErrorReport.TYPE_ANR;
7905 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007906
Dan Egnorb7f03672009-12-09 16:22:32 -08007907 report.anrInfo.activity = r.notRespondingReport.tag;
7908 report.anrInfo.cause = r.notRespondingReport.shortMsg;
7909 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007910 }
7911
Dan Egnorb7f03672009-12-09 16:22:32 -08007912 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007913 }
7914
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007915 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
7916 // assume our apps are happy - lazy create the list
7917 List<ActivityManager.ProcessErrorStateInfo> errList = null;
7918
7919 synchronized (this) {
7920
7921 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007922 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7923 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007924 if ((app.thread != null) && (app.crashing || app.notResponding)) {
7925 // This one's in trouble, so we'll generate a report for it
7926 // crashes are higher priority (in case there's a crash *and* an anr)
7927 ActivityManager.ProcessErrorStateInfo report = null;
7928 if (app.crashing) {
7929 report = app.crashingReport;
7930 } else if (app.notResponding) {
7931 report = app.notRespondingReport;
7932 }
7933
7934 if (report != null) {
7935 if (errList == null) {
7936 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
7937 }
7938 errList.add(report);
7939 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007940 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007941 " crashing = " + app.crashing +
7942 " notResponding = " + app.notResponding);
7943 }
7944 }
7945 }
7946 }
7947
7948 return errList;
7949 }
Dianne Hackborn905577f2011-09-07 18:31:28 -07007950
7951 static int oomAdjToImportance(int adj, ActivityManager.RunningAppProcessInfo currApp) {
Dianne Hackborne02c88a2011-10-28 13:58:15 -07007952 if (adj >= ProcessList.HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn905577f2011-09-07 18:31:28 -07007953 if (currApp != null) {
7954 currApp.lru = adj - ProcessList.HIDDEN_APP_MIN_ADJ + 1;
7955 }
7956 return ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
Dianne Hackborne02c88a2011-10-28 13:58:15 -07007957 } else if (adj >= ProcessList.SERVICE_B_ADJ) {
7958 return ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn905577f2011-09-07 18:31:28 -07007959 } else if (adj >= ProcessList.HOME_APP_ADJ) {
7960 if (currApp != null) {
7961 currApp.lru = 0;
7962 }
7963 return ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
Dianne Hackborne02c88a2011-10-28 13:58:15 -07007964 } else if (adj >= ProcessList.SERVICE_ADJ) {
Dianne Hackborn905577f2011-09-07 18:31:28 -07007965 return ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
7966 } else if (adj >= ProcessList.HEAVY_WEIGHT_APP_ADJ) {
7967 return ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE;
7968 } else if (adj >= ProcessList.PERCEPTIBLE_APP_ADJ) {
7969 return ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
7970 } else if (adj >= ProcessList.VISIBLE_APP_ADJ) {
7971 return ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
7972 } else {
7973 return ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
7974 }
7975 }
7976
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007977 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
7978 // Lazy instantiation of list
7979 List<ActivityManager.RunningAppProcessInfo> runList = null;
7980 synchronized (this) {
7981 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007982 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7983 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007984 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
7985 // Generate process state info for running application
7986 ActivityManager.RunningAppProcessInfo currApp =
7987 new ActivityManager.RunningAppProcessInfo(app.processName,
7988 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07007989 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007990 if (mHeavyWeightProcess == app) {
Dianne Hackborn482566e2010-09-03 12:51:28 -07007991 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007992 }
Dianne Hackborn42499172010-10-15 18:45:07 -07007993 if (app.persistent) {
7994 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_PERSISTENT;
7995 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007996 int adj = app.curAdj;
Dianne Hackborn905577f2011-09-07 18:31:28 -07007997 currApp.importance = oomAdjToImportance(adj, currApp);
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007998 currApp.importanceReasonCode = app.adjTypeCode;
7999 if (app.adjSource instanceof ProcessRecord) {
8000 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn905577f2011-09-07 18:31:28 -07008001 currApp.importanceReasonImportance = oomAdjToImportance(
8002 app.adjSourceOom, null);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008003 } else if (app.adjSource instanceof ActivityRecord) {
8004 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07008005 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
8006 }
8007 if (app.adjTarget instanceof ComponentName) {
8008 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
8009 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008010 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008011 // + " lru=" + currApp.lru);
8012 if (runList == null) {
8013 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
8014 }
8015 runList.add(currApp);
8016 }
8017 }
8018 }
8019 return runList;
8020 }
8021
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07008022 public List<ApplicationInfo> getRunningExternalApplications() {
8023 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
8024 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
8025 if (runningApps != null && runningApps.size() > 0) {
8026 Set<String> extList = new HashSet<String>();
8027 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
8028 if (app.pkgList != null) {
8029 for (String pkg : app.pkgList) {
8030 extList.add(pkg);
8031 }
8032 }
8033 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07008034 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07008035 for (String pkg : extList) {
8036 try {
8037 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
8038 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
8039 retList.add(info);
8040 }
8041 } catch (RemoteException e) {
8042 }
8043 }
8044 }
8045 return retList;
8046 }
8047
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008048 @Override
8049 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008050 if (checkCallingPermission(android.Manifest.permission.DUMP)
8051 != PackageManager.PERMISSION_GRANTED) {
8052 pw.println("Permission Denial: can't dump ActivityManager from from pid="
8053 + Binder.getCallingPid()
8054 + ", uid=" + Binder.getCallingUid()
8055 + " without permission "
8056 + android.Manifest.permission.DUMP);
8057 return;
8058 }
8059
8060 boolean dumpAll = false;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008061 boolean dumpClient = false;
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008062 String dumpPackage = null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008063
8064 int opti = 0;
8065 while (opti < args.length) {
8066 String opt = args[opti];
8067 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
8068 break;
8069 }
8070 opti++;
8071 if ("-a".equals(opt)) {
8072 dumpAll = true;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008073 } else if ("-c".equals(opt)) {
8074 dumpClient = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008075 } else if ("-h".equals(opt)) {
8076 pw.println("Activity manager dump options:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008077 pw.println(" [-a] [-c] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008078 pw.println(" cmd may be one of:");
Dianne Hackborn287952c2010-09-22 22:34:31 -07008079 pw.println(" a[ctivities]: activity stack state");
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008080 pw.println(" b[roadcasts] [PACKAGE_NAME]: broadcast state");
8081 pw.println(" i[ntents] [PACKAGE_NAME]: pending intent state");
8082 pw.println(" p[rocesses] [PACKAGE_NAME]: process state");
Dianne Hackborn287952c2010-09-22 22:34:31 -07008083 pw.println(" o[om]: out of memory management");
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07008084 pw.println(" prov[iders] [COMP_SPEC ...]: content provider state");
8085 pw.println(" s[ervices] [COMP_SPEC ...]: service state");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008086 pw.println(" service [COMP_SPEC]: service client-side state");
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008087 pw.println(" package [PACKAGE_NAME]: all state related to given package");
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07008088 pw.println(" all: dump all activities");
8089 pw.println(" top: dump the top activity");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008090 pw.println(" cmd may also be a COMP_SPEC to dump activities.");
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07008091 pw.println(" COMP_SPEC may be a component name (com.foo/.myApp),");
8092 pw.println(" a partial substring in a component name, a");
8093 pw.println(" hex object identifier.");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008094 pw.println(" -a: include all available server state.");
8095 pw.println(" -c: include client state.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008096 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008097 } else {
8098 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008099 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008100 }
8101
8102 // Is the caller requesting to dump a particular piece of data?
8103 if (opti < args.length) {
8104 String cmd = args[opti];
8105 opti++;
8106 if ("activities".equals(cmd) || "a".equals(cmd)) {
8107 synchronized (this) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008108 dumpActivitiesLocked(fd, pw, args, opti, true, dumpClient, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008109 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008110 return;
8111 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008112 String[] newArgs;
8113 String name;
8114 if (opti >= args.length) {
8115 name = null;
8116 newArgs = EMPTY_STRING_ARRAY;
8117 } else {
8118 name = args[opti];
8119 opti++;
8120 newArgs = new String[args.length - opti];
8121 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0,
8122 args.length - opti);
8123 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008124 synchronized (this) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008125 dumpBroadcastsLocked(fd, pw, args, opti, true, name);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008126 }
8127 return;
8128 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008129 String[] newArgs;
8130 String name;
8131 if (opti >= args.length) {
8132 name = null;
8133 newArgs = EMPTY_STRING_ARRAY;
8134 } else {
8135 name = args[opti];
8136 opti++;
8137 newArgs = new String[args.length - opti];
8138 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0,
8139 args.length - opti);
8140 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008141 synchronized (this) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008142 dumpPendingIntentsLocked(fd, pw, args, opti, true, name);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008143 }
8144 return;
8145 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008146 String[] newArgs;
8147 String name;
8148 if (opti >= args.length) {
8149 name = null;
8150 newArgs = EMPTY_STRING_ARRAY;
8151 } else {
8152 name = args[opti];
8153 opti++;
8154 newArgs = new String[args.length - opti];
8155 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0,
8156 args.length - opti);
8157 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008158 synchronized (this) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008159 dumpProcessesLocked(fd, pw, args, opti, true, name);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008160 }
8161 return;
Dianne Hackborn287952c2010-09-22 22:34:31 -07008162 } else if ("oom".equals(cmd) || "o".equals(cmd)) {
8163 synchronized (this) {
8164 dumpOomLocked(fd, pw, args, opti, true);
8165 }
8166 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008167 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
8168 synchronized (this) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008169 dumpProvidersLocked(fd, pw, args, opti, true, null);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008170 }
8171 return;
8172 } else if ("service".equals(cmd)) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008173 String[] newArgs;
8174 String name;
8175 if (opti >= args.length) {
8176 name = null;
8177 newArgs = EMPTY_STRING_ARRAY;
8178 } else {
8179 name = args[opti];
8180 opti++;
8181 newArgs = new String[args.length - opti];
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008182 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0,
8183 args.length - opti);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008184 }
8185 if (!dumpService(fd, pw, name, newArgs, 0, dumpAll)) {
8186 pw.println("No services match: " + name);
8187 pw.println("Use -h for help.");
8188 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008189 return;
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008190 } else if ("package".equals(cmd)) {
8191 String[] newArgs;
8192 if (opti >= args.length) {
8193 pw.println("package: no package name specified");
8194 pw.println("Use -h for help.");
8195 return;
8196 } else {
8197 dumpPackage = args[opti];
8198 opti++;
8199 newArgs = new String[args.length - opti];
8200 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0,
8201 args.length - opti);
8202 args = newArgs;
8203 opti = 0;
8204 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008205 } else if ("services".equals(cmd) || "s".equals(cmd)) {
8206 synchronized (this) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008207 dumpServicesLocked(fd, pw, args, opti, true, dumpClient, null);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008208 }
8209 return;
Dianne Hackborn625ac272010-09-17 18:29:22 -07008210 } else {
8211 // Dumping a single activity?
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008212 if (!dumpActivity(fd, pw, cmd, args, opti, dumpAll)) {
8213 pw.println("Bad activity command, or no activities match: " + cmd);
8214 pw.println("Use -h for help.");
Dianne Hackborn625ac272010-09-17 18:29:22 -07008215 }
Dianne Hackborn30d71892010-12-11 10:37:55 -08008216 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008217 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008218 }
8219
8220 // No piece of data specified, dump everything.
8221 synchronized (this) {
8222 boolean needSep;
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008223 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll, dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008224 if (needSep) {
8225 pw.println(" ");
8226 }
8227 if (dumpAll) {
8228 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008229 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008230 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll, dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008231 if (needSep) {
8232 pw.println(" ");
8233 }
8234 if (dumpAll) {
8235 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008236 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008237 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll, dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008238 if (needSep) {
8239 pw.println(" ");
8240 }
8241 if (dumpAll) {
8242 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008243 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008244 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll, dumpClient, dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008245 if (needSep) {
8246 pw.println(" ");
8247 }
8248 if (dumpAll) {
8249 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008250 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008251 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, dumpClient, dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008252 if (needSep) {
8253 pw.println(" ");
8254 }
8255 if (dumpAll) {
8256 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008257 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008258 dumpProcessesLocked(fd, pw, args, opti, dumpAll, dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008259 }
8260 }
8261
8262 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008263 int opti, boolean dumpAll, boolean dumpClient, String dumpPackage) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008264 pw.println("ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)");
8265 pw.println(" Main stack:");
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008266 dumpHistoryList(fd, pw, mMainStack.mHistory, " ", "Hist", true, !dumpAll, dumpClient,
8267 dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008268 pw.println(" ");
8269 pw.println(" Running activities (most recent first):");
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008270 dumpHistoryList(fd, pw, mMainStack.mLRUActivities, " ", "Run", false, !dumpAll, false,
8271 dumpPackage);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008272 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008273 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008274 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008275 dumpHistoryList(fd, pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false,
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008276 !dumpAll, false, dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008277 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008278 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008279 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008280 pw.println(" Activities waiting to stop:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008281 dumpHistoryList(fd, pw, mMainStack.mStoppingActivities, " ", "Stop", false,
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008282 !dumpAll, false, dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008283 }
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08008284 if (mMainStack.mGoingToSleepActivities.size() > 0) {
8285 pw.println(" ");
8286 pw.println(" Activities waiting to sleep:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008287 dumpHistoryList(fd, pw, mMainStack.mGoingToSleepActivities, " ", "Sleep", false,
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008288 !dumpAll, false, dumpPackage);
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08008289 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008290 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008291 pw.println(" ");
8292 pw.println(" Activities waiting to finish:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008293 dumpHistoryList(fd, pw, mMainStack.mFinishingActivities, " ", "Fin", false,
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008294 !dumpAll, false, dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008295 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008296
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008297 pw.println(" ");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008298 if (mMainStack.mPausingActivity != null) {
8299 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
8300 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008301 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008302 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008303 if (dumpAll) {
8304 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
8305 pw.println(" mSleepTimeout: " + mMainStack.mSleepTimeout);
Dianne Hackborn90c52de2011-09-23 12:57:44 -07008306 pw.println(" mDismissKeyguardOnNextActivity: "
8307 + mMainStack.mDismissKeyguardOnNextActivity);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008308 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008309
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008310 if (mRecentTasks.size() > 0) {
8311 pw.println();
8312 pw.println(" Recent tasks:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008313
8314 final int N = mRecentTasks.size();
8315 for (int i=0; i<N; i++) {
8316 TaskRecord tr = mRecentTasks.get(i);
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008317 if (dumpPackage != null) {
8318 if (tr.realActivity == null ||
8319 !dumpPackage.equals(tr.realActivity)) {
8320 continue;
8321 }
8322 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008323 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
8324 pw.println(tr);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008325 if (dumpAll) {
8326 mRecentTasks.get(i).dump(pw, " ");
8327 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008328 }
8329 }
8330
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008331 if (dumpAll) {
8332 pw.println(" ");
8333 pw.println(" mCurTask: " + mCurTask);
8334 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008335
8336 return true;
8337 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07008338
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008339 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008340 int opti, boolean dumpAll, String dumpPackage) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008341 boolean needSep = false;
8342 int numPers = 0;
8343
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008344 pw.println("ACTIVITY MANAGER RUNNING PROCESSES (dumpsys activity processes)");
8345
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008346 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008347 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
8348 final int NA = procs.size();
8349 for (int ia=0; ia<NA; ia++) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008350 ProcessRecord r = procs.valueAt(ia);
8351 if (dumpPackage != null && !dumpPackage.equals(r.info.packageName)) {
8352 continue;
8353 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008354 if (!needSep) {
8355 pw.println(" All known processes:");
8356 needSep = true;
8357 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008358 pw.print(r.persistent ? " *PERS*" : " *APP*");
8359 pw.print(" UID "); pw.print(procs.keyAt(ia));
8360 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008361 r.dump(pw, " ");
8362 if (r.persistent) {
8363 numPers++;
8364 }
8365 }
8366 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008367 }
8368
8369 if (mLruProcesses.size() > 0) {
8370 if (needSep) pw.println(" ");
8371 needSep = true;
Dianne Hackborn905577f2011-09-07 18:31:28 -07008372 pw.println(" Process LRU list (sorted by oom_adj):");
Dianne Hackborn287952c2010-09-22 22:34:31 -07008373 dumpProcessOomList(pw, this, mLruProcesses, " ",
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008374 "Proc", "PERS", false, dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008375 needSep = true;
8376 }
8377
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008378 if (dumpAll) {
8379 synchronized (mPidsSelfLocked) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008380 boolean printed = false;
8381 for (int i=0; i<mPidsSelfLocked.size(); i++) {
8382 ProcessRecord r = mPidsSelfLocked.valueAt(i);
8383 if (dumpPackage != null && !dumpPackage.equals(r.info.packageName)) {
8384 continue;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008385 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008386 if (!printed) {
8387 if (needSep) pw.println(" ");
8388 needSep = true;
8389 pw.println(" PID mappings:");
8390 printed = true;
8391 }
8392 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
8393 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008394 }
8395 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008396 }
8397
8398 if (mForegroundProcesses.size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008399 synchronized (mPidsSelfLocked) {
8400 boolean printed = false;
8401 for (int i=0; i<mForegroundProcesses.size(); i++) {
8402 ProcessRecord r = mPidsSelfLocked.get(
8403 mForegroundProcesses.valueAt(i).pid);
8404 if (dumpPackage != null && (r == null
8405 || !dumpPackage.equals(r.info.packageName))) {
8406 continue;
8407 }
8408 if (!printed) {
8409 if (needSep) pw.println(" ");
8410 needSep = true;
8411 pw.println(" Foreground Processes:");
8412 printed = true;
8413 }
8414 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
8415 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
8416 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008417 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008418 }
8419
8420 if (mPersistentStartingProcesses.size() > 0) {
8421 if (needSep) pw.println(" ");
8422 needSep = true;
8423 pw.println(" Persisent processes that are starting:");
8424 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008425 "Starting Norm", "Restarting PERS", dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008426 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008427
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008428 if (mRemovedProcesses.size() > 0) {
8429 if (needSep) pw.println(" ");
8430 needSep = true;
8431 pw.println(" Processes that are being removed:");
8432 dumpProcessList(pw, this, mRemovedProcesses, " ",
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008433 "Removed Norm", "Removed PERS", dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008434 }
8435
8436 if (mProcessesOnHold.size() > 0) {
8437 if (needSep) pw.println(" ");
8438 needSep = true;
8439 pw.println(" Processes that are on old until the system is ready:");
8440 dumpProcessList(pw, this, mProcessesOnHold, " ",
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008441 "OnHold Norm", "OnHold PERS", dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008442 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008443
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008444 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll, dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008445
8446 if (mProcessCrashTimes.getMap().size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008447 boolean printed = false;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008448 long now = SystemClock.uptimeMillis();
8449 for (Map.Entry<String, SparseArray<Long>> procs
8450 : mProcessCrashTimes.getMap().entrySet()) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008451 String pname = procs.getKey();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008452 SparseArray<Long> uids = procs.getValue();
8453 final int N = uids.size();
8454 for (int i=0; i<N; i++) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008455 int puid = uids.keyAt(i);
8456 ProcessRecord r = mProcessNames.get(pname, puid);
8457 if (dumpPackage != null && (r == null
8458 || !dumpPackage.equals(r.info.packageName))) {
8459 continue;
8460 }
8461 if (!printed) {
8462 if (needSep) pw.println(" ");
8463 needSep = true;
8464 pw.println(" Time since processes crashed:");
8465 printed = true;
8466 }
8467 pw.print(" Process "); pw.print(pname);
8468 pw.print(" uid "); pw.print(puid);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008469 pw.print(": last crashed ");
8470 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008471 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008472 }
8473 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008474 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008475
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008476 if (mBadProcesses.getMap().size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008477 boolean printed = false;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008478 for (Map.Entry<String, SparseArray<Long>> procs
8479 : mBadProcesses.getMap().entrySet()) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008480 String pname = procs.getKey();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008481 SparseArray<Long> uids = procs.getValue();
8482 final int N = uids.size();
8483 for (int i=0; i<N; i++) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008484 int puid = uids.keyAt(i);
8485 ProcessRecord r = mProcessNames.get(pname, puid);
8486 if (dumpPackage != null && (r == null
8487 || !dumpPackage.equals(r.info.packageName))) {
8488 continue;
8489 }
8490 if (!printed) {
8491 if (needSep) pw.println(" ");
8492 needSep = true;
8493 pw.println(" Bad processes:");
8494 }
8495 pw.print(" Bad process "); pw.print(pname);
8496 pw.print(" uid "); pw.print(puid);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008497 pw.print(": crashed at time ");
8498 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008499 }
8500 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008501 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008502
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008503 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008504 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackbornf35fe232011-11-01 19:25:20 -07008505 pw.println(" mPreviousProcess: " + mPreviousProcess);
Dianne Hackborn50685602011-12-01 12:23:37 -08008506 if (dumpAll) {
8507 StringBuilder sb = new StringBuilder(128);
8508 sb.append(" mPreviousProcessVisibleTime: ");
8509 TimeUtils.formatDuration(mPreviousProcessVisibleTime, sb);
8510 pw.println(sb);
8511 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07008512 if (mHeavyWeightProcess != null) {
8513 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
8514 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008515 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008516 if (dumpAll) {
8517 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackborn3d0724d2011-05-12 15:39:41 -07008518 if (mCompatModePackages.getPackages().size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008519 boolean printed = false;
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07008520 for (Map.Entry<String, Integer> entry
8521 : mCompatModePackages.getPackages().entrySet()) {
8522 String pkg = entry.getKey();
8523 int mode = entry.getValue();
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008524 if (dumpPackage != null && !dumpPackage.equals(pkg)) {
8525 continue;
8526 }
8527 if (!printed) {
8528 pw.println(" mScreenCompatPackages:");
8529 printed = true;
8530 }
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07008531 pw.print(" "); pw.print(pkg); pw.print(": ");
8532 pw.print(mode); pw.println();
8533 }
Dianne Hackbornaa9d84c2011-05-09 19:00:59 -07008534 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008535 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008536 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
8537 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
8538 || mOrigWaitForDebugger) {
8539 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
8540 + " mDebugTransient=" + mDebugTransient
8541 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
8542 }
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07008543 if (mProfileApp != null || mProfileProc != null || mProfileFile != null
8544 || mProfileFd != null) {
8545 pw.println(" mProfileApp=" + mProfileApp + " mProfileProc=" + mProfileProc);
8546 pw.println(" mProfileFile=" + mProfileFile + " mProfileFd=" + mProfileFd);
8547 pw.println(" mProfileType=" + mProfileType + " mAutoStopProfiler="
8548 + mAutoStopProfiler);
8549 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008550 if (mAlwaysFinishActivities || mController != null) {
8551 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
8552 + " mController=" + mController);
8553 }
8554 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008555 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008556 pw.println(" mStartRunning=" + mStartRunning
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07008557 + " mProcessesReady=" + mProcessesReady
8558 + " mSystemReady=" + mSystemReady);
8559 pw.println(" mBooting=" + mBooting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008560 + " mBooted=" + mBooted
8561 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008562 pw.print(" mLastPowerCheckRealtime=");
8563 TimeUtils.formatDuration(mLastPowerCheckRealtime, pw);
8564 pw.println("");
8565 pw.print(" mLastPowerCheckUptime=");
8566 TimeUtils.formatDuration(mLastPowerCheckUptime, pw);
8567 pw.println("");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008568 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
8569 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07008570 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
Dianne Hackborne02c88a2011-10-28 13:58:15 -07008571 pw.println(" mNumServiceProcs=" + mNumServiceProcs
8572 + " mNewNumServiceProcs=" + mNewNumServiceProcs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008573 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008574
8575 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008576 }
8577
Dianne Hackborn287952c2010-09-22 22:34:31 -07008578 boolean dumpProcessesToGc(FileDescriptor fd, PrintWriter pw, String[] args,
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008579 int opti, boolean needSep, boolean dumpAll, String dumpPackage) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07008580 if (mProcessesToGc.size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008581 boolean printed = false;
Dianne Hackborn287952c2010-09-22 22:34:31 -07008582 long now = SystemClock.uptimeMillis();
8583 for (int i=0; i<mProcessesToGc.size(); i++) {
8584 ProcessRecord proc = mProcessesToGc.get(i);
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008585 if (dumpPackage != null && !dumpPackage.equals(proc.info.packageName)) {
8586 continue;
8587 }
8588 if (!printed) {
8589 if (needSep) pw.println(" ");
8590 needSep = true;
8591 pw.println(" Processes that are waiting to GC:");
8592 printed = true;
8593 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07008594 pw.print(" Process "); pw.println(proc);
8595 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
8596 pw.print(", last gced=");
8597 pw.print(now-proc.lastRequestedGc);
8598 pw.print(" ms ago, last lowMem=");
8599 pw.print(now-proc.lastLowMemory);
8600 pw.println(" ms ago");
8601
8602 }
8603 }
8604 return needSep;
8605 }
8606
8607 boolean dumpOomLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8608 int opti, boolean dumpAll) {
8609 boolean needSep = false;
8610
8611 if (mLruProcesses.size() > 0) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07008612 if (needSep) pw.println(" ");
8613 needSep = true;
Dianne Hackbornc68c9132011-07-29 01:25:18 -07008614 pw.println(" OOM levels:");
Dianne Hackborn7d608422011-08-07 16:24:18 -07008615 pw.print(" SYSTEM_ADJ: "); pw.println(ProcessList.SYSTEM_ADJ);
Dianne Hackborne02c88a2011-10-28 13:58:15 -07008616 pw.print(" PERSISTENT_PROC_ADJ: "); pw.println(ProcessList.PERSISTENT_PROC_ADJ);
Dianne Hackborn7d608422011-08-07 16:24:18 -07008617 pw.print(" FOREGROUND_APP_ADJ: "); pw.println(ProcessList.FOREGROUND_APP_ADJ);
8618 pw.print(" VISIBLE_APP_ADJ: "); pw.println(ProcessList.VISIBLE_APP_ADJ);
8619 pw.print(" PERCEPTIBLE_APP_ADJ: "); pw.println(ProcessList.PERCEPTIBLE_APP_ADJ);
8620 pw.print(" HEAVY_WEIGHT_APP_ADJ: "); pw.println(ProcessList.HEAVY_WEIGHT_APP_ADJ);
8621 pw.print(" BACKUP_APP_ADJ: "); pw.println(ProcessList.BACKUP_APP_ADJ);
Dianne Hackborne02c88a2011-10-28 13:58:15 -07008622 pw.print(" SERVICE_ADJ: "); pw.println(ProcessList.SERVICE_ADJ);
Dianne Hackborn7d608422011-08-07 16:24:18 -07008623 pw.print(" HOME_APP_ADJ: "); pw.println(ProcessList.HOME_APP_ADJ);
Dianne Hackbornf35fe232011-11-01 19:25:20 -07008624 pw.print(" PREVIOUS_APP_ADJ: "); pw.println(ProcessList.PREVIOUS_APP_ADJ);
Dianne Hackborne02c88a2011-10-28 13:58:15 -07008625 pw.print(" SERVICE_B_ADJ: "); pw.println(ProcessList.SERVICE_B_ADJ);
Dianne Hackborn7d608422011-08-07 16:24:18 -07008626 pw.print(" HIDDEN_APP_MIN_ADJ: "); pw.println(ProcessList.HIDDEN_APP_MIN_ADJ);
Dianne Hackborne02c88a2011-10-28 13:58:15 -07008627 pw.print(" HIDDEN_APP_MAX_ADJ: "); pw.println(ProcessList.HIDDEN_APP_MAX_ADJ);
Dianne Hackbornc68c9132011-07-29 01:25:18 -07008628
8629 if (needSep) pw.println(" ");
8630 needSep = true;
Dianne Hackborn287952c2010-09-22 22:34:31 -07008631 pw.println(" Process OOM control:");
Dianne Hackborn905577f2011-09-07 18:31:28 -07008632 dumpProcessOomList(pw, this, mLruProcesses, " ",
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008633 "Proc", "PERS", true, null);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008634 needSep = true;
8635 }
8636
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008637 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll, null);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008638
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008639 pw.println();
Dianne Hackborn287952c2010-09-22 22:34:31 -07008640 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackbornf35fe232011-11-01 19:25:20 -07008641 pw.println(" mPreviousProcess: " + mPreviousProcess);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008642 if (mHeavyWeightProcess != null) {
8643 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
8644 }
8645
8646 return true;
8647 }
8648
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008649 /**
8650 * There are three ways to call this:
8651 * - no service specified: dump all the services
8652 * - a flattened component name that matched an existing service was specified as the
8653 * first arg: dump that one service
8654 * - the first arg isn't the flattened component name of an existing service:
8655 * dump all services whose component contains the first arg as a substring
8656 */
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008657 protected boolean dumpService(FileDescriptor fd, PrintWriter pw, String name, String[] args,
8658 int opti, boolean dumpAll) {
8659 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008660
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008661 if ("all".equals(name)) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07008662 synchronized (this) {
8663 for (ServiceRecord r1 : mServices.values()) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008664 services.add(r1);
8665 }
8666 }
8667 } else {
8668 ComponentName componentName = name != null
8669 ? ComponentName.unflattenFromString(name) : null;
8670 int objectId = 0;
8671 if (componentName == null) {
8672 // Not a '/' separated full component name; maybe an object ID?
8673 try {
8674 objectId = Integer.parseInt(name, 16);
8675 name = null;
8676 componentName = null;
8677 } catch (RuntimeException e) {
8678 }
8679 }
8680
8681 synchronized (this) {
8682 for (ServiceRecord r1 : mServices.values()) {
8683 if (componentName != null) {
8684 if (r1.name.equals(componentName)) {
8685 services.add(r1);
8686 }
8687 } else if (name != null) {
8688 if (r1.name.flattenToString().contains(name)) {
8689 services.add(r1);
8690 }
8691 } else if (System.identityHashCode(r1) == objectId) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07008692 services.add(r1);
8693 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008694 }
8695 }
8696 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008697
8698 if (services.size() <= 0) {
8699 return false;
8700 }
8701
8702 boolean needSep = false;
8703 for (int i=0; i<services.size(); i++) {
8704 if (needSep) {
8705 pw.println();
8706 }
8707 needSep = true;
8708 dumpService("", fd, pw, services.get(i), args, dumpAll);
8709 }
8710 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008711 }
8712
8713 /**
8714 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
8715 * there is a thread associated with the service.
8716 */
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008717 private void dumpService(String prefix, FileDescriptor fd, PrintWriter pw,
8718 final ServiceRecord r, String[] args, boolean dumpAll) {
8719 String innerPrefix = prefix + " ";
8720 synchronized (this) {
8721 pw.print(prefix); pw.print("SERVICE ");
8722 pw.print(r.shortName); pw.print(" ");
8723 pw.print(Integer.toHexString(System.identityHashCode(r)));
8724 pw.print(" pid=");
8725 if (r.app != null) pw.println(r.app.pid);
8726 else pw.println("(not running)");
8727 if (dumpAll) {
8728 r.dump(pw, innerPrefix);
8729 }
8730 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008731 if (r.app != null && r.app.thread != null) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008732 pw.print(prefix); pw.println(" Client:");
8733 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008734 try {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008735 TransferPipe tp = new TransferPipe();
8736 try {
8737 r.app.thread.dumpService(tp.getWriteFd().getFileDescriptor(), r, args);
8738 tp.setBufferPrefix(prefix + " ");
8739 tp.go(fd);
8740 } finally {
8741 tp.kill();
8742 }
8743 } catch (IOException e) {
8744 pw.println(prefix + " Failure while dumping the service: " + e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008745 } catch (RemoteException e) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008746 pw.println(prefix + " Got a RemoteException while dumping the service");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008747 }
8748 }
8749 }
8750
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07008751 static class ItemMatcher {
8752 ArrayList<ComponentName> components;
8753 ArrayList<String> strings;
8754 ArrayList<Integer> objects;
8755 boolean all;
8756
8757 ItemMatcher() {
8758 all = true;
8759 }
8760
8761 void build(String name) {
8762 ComponentName componentName = ComponentName.unflattenFromString(name);
8763 if (componentName != null) {
8764 if (components == null) {
8765 components = new ArrayList<ComponentName>();
8766 }
8767 components.add(componentName);
8768 all = false;
8769 } else {
8770 int objectId = 0;
8771 // Not a '/' separated full component name; maybe an object ID?
8772 try {
8773 objectId = Integer.parseInt(name, 16);
8774 if (objects == null) {
8775 objects = new ArrayList<Integer>();
8776 }
8777 objects.add(objectId);
8778 all = false;
8779 } catch (RuntimeException e) {
8780 // Not an integer; just do string match.
8781 if (strings == null) {
8782 strings = new ArrayList<String>();
8783 }
8784 strings.add(name);
8785 all = false;
8786 }
8787 }
8788 }
8789
8790 int build(String[] args, int opti) {
8791 for (; opti<args.length; opti++) {
8792 String name = args[opti];
8793 if ("--".equals(name)) {
8794 return opti+1;
8795 }
8796 build(name);
8797 }
8798 return opti;
8799 }
8800
8801 boolean match(Object object, ComponentName comp) {
8802 if (all) {
8803 return true;
8804 }
8805 if (components != null) {
8806 for (int i=0; i<components.size(); i++) {
8807 if (components.get(i).equals(comp)) {
8808 return true;
8809 }
8810 }
8811 }
8812 if (objects != null) {
8813 for (int i=0; i<objects.size(); i++) {
8814 if (System.identityHashCode(object) == objects.get(i)) {
8815 return true;
8816 }
8817 }
8818 }
8819 if (strings != null) {
8820 String flat = comp.flattenToString();
8821 for (int i=0; i<strings.size(); i++) {
8822 if (flat.contains(strings.get(i))) {
8823 return true;
8824 }
8825 }
8826 }
8827 return false;
8828 }
8829 }
8830
Dianne Hackborn625ac272010-09-17 18:29:22 -07008831 /**
8832 * There are three things that cmd can be:
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07008833 * - a flattened component name that matches an existing activity
Dianne Hackborn625ac272010-09-17 18:29:22 -07008834 * - the cmd arg isn't the flattened component name of an existing activity:
8835 * dump all activity whose component contains the cmd as a substring
8836 * - A hex number of the ActivityRecord object instance.
8837 */
8838 protected boolean dumpActivity(FileDescriptor fd, PrintWriter pw, String name, String[] args,
8839 int opti, boolean dumpAll) {
Dianne Hackborn625ac272010-09-17 18:29:22 -07008840 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008841
8842 if ("all".equals(name)) {
8843 synchronized (this) {
8844 for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
Dianne Hackborn625ac272010-09-17 18:29:22 -07008845 activities.add(r1);
8846 }
8847 }
Dianne Hackbornf9302322011-06-14 18:36:14 -07008848 } else if ("top".equals(name)) {
8849 synchronized (this) {
8850 final int N = mMainStack.mHistory.size();
8851 if (N > 0) {
8852 activities.add((ActivityRecord)mMainStack.mHistory.get(N-1));
8853 }
8854 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008855 } else {
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07008856 ItemMatcher matcher = new ItemMatcher();
8857 matcher.build(name);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008858
8859 synchronized (this) {
8860 for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07008861 if (matcher.match(r1, r1.intent.getComponent())) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008862 activities.add(r1);
8863 }
8864 }
8865 }
Dianne Hackborn625ac272010-09-17 18:29:22 -07008866 }
8867
8868 if (activities.size() <= 0) {
8869 return false;
8870 }
8871
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008872 String[] newArgs = new String[args.length - opti];
8873 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
8874
Dianne Hackborn30d71892010-12-11 10:37:55 -08008875 TaskRecord lastTask = null;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008876 boolean needSep = false;
Dianne Hackborn30d71892010-12-11 10:37:55 -08008877 for (int i=activities.size()-1; i>=0; i--) {
8878 ActivityRecord r = (ActivityRecord)activities.get(i);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008879 if (needSep) {
8880 pw.println();
8881 }
8882 needSep = true;
8883 synchronized (this) {
8884 if (lastTask != r.task) {
8885 lastTask = r.task;
8886 pw.print("TASK "); pw.print(lastTask.affinity);
8887 pw.print(" id="); pw.println(lastTask.taskId);
8888 if (dumpAll) {
8889 lastTask.dump(pw, " ");
8890 }
Dianne Hackborn30d71892010-12-11 10:37:55 -08008891 }
8892 }
8893 dumpActivity(" ", fd, pw, activities.get(i), newArgs, dumpAll);
Dianne Hackborn625ac272010-09-17 18:29:22 -07008894 }
8895 return true;
8896 }
8897
8898 /**
8899 * Invokes IApplicationThread.dumpActivity() on the thread of the specified activity if
8900 * there is a thread associated with the activity.
8901 */
Dianne Hackborn30d71892010-12-11 10:37:55 -08008902 private void dumpActivity(String prefix, FileDescriptor fd, PrintWriter pw,
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008903 final ActivityRecord r, String[] args, boolean dumpAll) {
8904 String innerPrefix = prefix + " ";
Dianne Hackborn30d71892010-12-11 10:37:55 -08008905 synchronized (this) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008906 pw.print(prefix); pw.print("ACTIVITY "); pw.print(r.shortComponentName);
8907 pw.print(" "); pw.print(Integer.toHexString(System.identityHashCode(r)));
8908 pw.print(" pid=");
Dianne Hackborn30d71892010-12-11 10:37:55 -08008909 if (r.app != null) pw.println(r.app.pid);
8910 else pw.println("(not running)");
8911 if (dumpAll) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008912 r.dump(pw, innerPrefix);
Dianne Hackborn625ac272010-09-17 18:29:22 -07008913 }
Dianne Hackborn625ac272010-09-17 18:29:22 -07008914 }
8915 if (r.app != null && r.app.thread != null) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008916 // flush anything that is already in the PrintWriter since the thread is going
8917 // to write to the file descriptor directly
8918 pw.flush();
Dianne Hackborn625ac272010-09-17 18:29:22 -07008919 try {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008920 TransferPipe tp = new TransferPipe();
8921 try {
Dianne Hackbornbe707852011-11-11 14:32:10 -08008922 r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(),
8923 r.appToken, innerPrefix, args);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008924 tp.go(fd);
8925 } finally {
8926 tp.kill();
8927 }
8928 } catch (IOException e) {
8929 pw.println(innerPrefix + "Failure while dumping the activity: " + e);
Dianne Hackborn625ac272010-09-17 18:29:22 -07008930 } catch (RemoteException e) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008931 pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
Dianne Hackborn625ac272010-09-17 18:29:22 -07008932 }
8933 }
8934 }
8935
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008936 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008937 int opti, boolean dumpAll, String dumpPackage) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008938 boolean needSep = false;
8939
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008940 pw.println("ACTIVITY MANAGER BROADCAST STATE (dumpsys activity broadcasts)");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008941 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008942 if (mRegisteredReceivers.size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008943 boolean printed = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008944 Iterator it = mRegisteredReceivers.values().iterator();
8945 while (it.hasNext()) {
8946 ReceiverList r = (ReceiverList)it.next();
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008947 if (dumpPackage != null && (r.app == null ||
8948 !dumpPackage.equals(r.app.info.packageName))) {
8949 continue;
8950 }
8951 if (!printed) {
8952 pw.println(" Registered Receivers:");
8953 needSep = true;
8954 printed = true;
8955 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008956 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008957 r.dump(pw, " ");
8958 }
8959 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008960
8961 if (mReceiverResolver.dump(pw, needSep ?
8962 "\n Receiver Resolver Table:" : " Receiver Resolver Table:",
8963 " ", dumpPackage, false)) {
8964 needSep = true;
8965 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008966 }
8967
8968 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
8969 || mPendingBroadcast != null) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008970 boolean printed = false;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008971 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008972 BroadcastRecord br = mParallelBroadcasts.get(i);
8973 if (dumpPackage != null && !dumpPackage.equals(br.callerPackage)) {
8974 continue;
8975 }
8976 if (!printed) {
8977 if (needSep) {
8978 pw.println();
8979 }
8980 needSep = true;
8981 pw.println(" Active broadcasts:");
8982 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008983 pw.println(" Broadcast #" + i + ":");
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008984 br.dump(pw, " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008985 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008986 printed = false;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008987 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008988 BroadcastRecord br = mOrderedBroadcasts.get(i);
8989 if (dumpPackage != null && !dumpPackage.equals(br.callerPackage)) {
8990 continue;
8991 }
8992 if (!printed) {
8993 if (needSep) {
8994 pw.println();
8995 }
8996 needSep = true;
8997 pw.println(" Active ordered broadcasts:");
8998 }
8999 pw.println(" Ordered Broadcast #" + i + ":");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009000 mOrderedBroadcasts.get(i).dump(pw, " ");
9001 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009002 if (dumpPackage == null || (mPendingBroadcast != null
9003 && dumpPackage.equals(mPendingBroadcast.callerPackage))) {
9004 if (needSep) {
9005 pw.println();
9006 }
9007 pw.println(" Pending broadcast:");
9008 if (mPendingBroadcast != null) {
9009 mPendingBroadcast.dump(pw, " ");
9010 } else {
9011 pw.println(" (null)");
9012 }
9013 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009014 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009015 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009016
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009017 boolean printed = false;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009018 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
9019 BroadcastRecord r = mBroadcastHistory[i];
9020 if (r == null) {
9021 break;
9022 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009023 if (dumpPackage != null && !dumpPackage.equals(r.callerPackage)) {
9024 continue;
9025 }
9026 if (!printed) {
9027 if (needSep) {
9028 pw.println();
9029 }
9030 needSep = true;
9031 pw.println(" Historical broadcasts:");
9032 printed = true;
9033 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009034 if (dumpAll) {
9035 pw.print(" Historical Broadcast #"); pw.print(i); pw.println(":");
9036 r.dump(pw, " ");
9037 } else {
9038 if (i >= 50) {
9039 pw.println(" ...");
Dianne Hackborn12527f92009-11-11 17:39:50 -08009040 break;
9041 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009042 pw.print(" #"); pw.print(i); pw.print(": "); pw.println(r);
Dianne Hackborn12527f92009-11-11 17:39:50 -08009043 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009044 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009045 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009046
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009047 if (mStickyBroadcasts != null && dumpPackage == null) {
9048 if (needSep) {
9049 pw.println();
9050 }
9051 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009052 pw.println(" Sticky broadcasts:");
9053 StringBuilder sb = new StringBuilder(128);
9054 for (Map.Entry<String, ArrayList<Intent>> ent
9055 : mStickyBroadcasts.entrySet()) {
9056 pw.print(" * Sticky action "); pw.print(ent.getKey());
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009057 if (dumpAll) {
9058 pw.println(":");
9059 ArrayList<Intent> intents = ent.getValue();
9060 final int N = intents.size();
9061 for (int i=0; i<N; i++) {
9062 sb.setLength(0);
9063 sb.append(" Intent: ");
Dianne Hackborn90c52de2011-09-23 12:57:44 -07009064 intents.get(i).toShortString(sb, false, true, false);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009065 pw.println(sb.toString());
9066 Bundle bundle = intents.get(i).getExtras();
9067 if (bundle != null) {
9068 pw.print(" ");
9069 pw.println(bundle.toString());
9070 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009071 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009072 } else {
9073 pw.println("");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009074 }
9075 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009076 needSep = true;
9077 }
9078
9079 if (dumpAll) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009080 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009081 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009082 pw.println(" mHandler:");
9083 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009084 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009085 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009086
9087 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009088 }
9089
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009090 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009091 int opti, boolean dumpAll, boolean dumpClient, String dumpPackage) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009092 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009093
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07009094 ItemMatcher matcher = new ItemMatcher();
9095 matcher.build(args, opti);
9096
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009097 pw.println("ACTIVITY MANAGER SERVICES (dumpsys activity services)");
9098 if (mServices.size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009099 boolean printed = false;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009100 long nowReal = SystemClock.elapsedRealtime();
9101 Iterator<ServiceRecord> it = mServices.values().iterator();
9102 needSep = false;
9103 while (it.hasNext()) {
9104 ServiceRecord r = it.next();
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07009105 if (!matcher.match(r, r.name)) {
9106 continue;
9107 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009108 if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
9109 continue;
9110 }
9111 if (!printed) {
9112 pw.println(" Active services:");
9113 printed = true;
9114 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009115 if (needSep) {
9116 pw.println();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009117 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009118 pw.print(" * "); pw.println(r);
9119 if (dumpAll) {
9120 r.dump(pw, " ");
9121 needSep = true;
9122 } else {
9123 pw.print(" app="); pw.println(r.app);
9124 pw.print(" created=");
9125 TimeUtils.formatDuration(r.createTime, nowReal, pw);
9126 pw.print(" started="); pw.print(r.startRequested);
9127 pw.print(" connections="); pw.println(r.connections.size());
Dianne Hackborn8ec8d412011-11-14 18:27:24 -08009128 if (r.connections.size() > 0) {
9129 pw.println(" Connections:");
9130 for (ArrayList<ConnectionRecord> clist : r.connections.values()) {
9131 for (int i=0; i<clist.size(); i++) {
9132 ConnectionRecord conn = clist.get(i);
9133 pw.print(" ");
9134 pw.print(conn.binding.intent.intent.getIntent().toShortString(
9135 false, false, false));
9136 pw.print(" -> ");
9137 ProcessRecord proc = conn.binding.client;
9138 pw.println(proc != null ? proc.toShortString() : "null");
9139 }
9140 }
9141 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009142 }
9143 if (dumpClient && r.app != null && r.app.thread != null) {
9144 pw.println(" Client:");
9145 pw.flush();
9146 try {
9147 TransferPipe tp = new TransferPipe();
9148 try {
9149 r.app.thread.dumpService(
9150 tp.getWriteFd().getFileDescriptor(), r, args);
9151 tp.setBufferPrefix(" ");
9152 // Short timeout, since blocking here can
9153 // deadlock with the application.
9154 tp.go(fd, 2000);
9155 } finally {
9156 tp.kill();
9157 }
9158 } catch (IOException e) {
9159 pw.println(" Failure while dumping the service: " + e);
9160 } catch (RemoteException e) {
9161 pw.println(" Got a RemoteException while dumping the service");
9162 }
9163 needSep = true;
9164 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009165 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009166 needSep = printed;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009167 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009168
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009169 if (mPendingServices.size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009170 boolean printed = false;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009171 for (int i=0; i<mPendingServices.size(); i++) {
9172 ServiceRecord r = mPendingServices.get(i);
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07009173 if (!matcher.match(r, r.name)) {
9174 continue;
9175 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009176 if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
9177 continue;
9178 }
9179 if (!printed) {
9180 if (needSep) pw.println(" ");
9181 needSep = true;
9182 pw.println(" Pending services:");
9183 printed = true;
9184 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009185 pw.print(" * Pending "); pw.println(r);
9186 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009187 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009188 needSep = true;
9189 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009190
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009191 if (mRestartingServices.size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009192 boolean printed = false;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009193 for (int i=0; i<mRestartingServices.size(); i++) {
9194 ServiceRecord r = mRestartingServices.get(i);
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07009195 if (!matcher.match(r, r.name)) {
9196 continue;
9197 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009198 if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
9199 continue;
9200 }
9201 if (!printed) {
9202 if (needSep) pw.println(" ");
9203 needSep = true;
9204 pw.println(" Restarting services:");
9205 printed = true;
9206 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009207 pw.print(" * Restarting "); pw.println(r);
9208 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009209 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009210 needSep = true;
9211 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009212
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009213 if (mStoppingServices.size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009214 boolean printed = false;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009215 for (int i=0; i<mStoppingServices.size(); i++) {
9216 ServiceRecord r = mStoppingServices.get(i);
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07009217 if (!matcher.match(r, r.name)) {
9218 continue;
9219 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009220 if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
9221 continue;
9222 }
9223 if (!printed) {
9224 if (needSep) pw.println(" ");
9225 needSep = true;
9226 pw.println(" Stopping services:");
9227 printed = true;
9228 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009229 pw.print(" * Stopping "); pw.println(r);
9230 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009231 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009232 needSep = true;
9233 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009234
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009235 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009236 if (mServiceConnections.size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009237 boolean printed = false;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009238 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009239 = mServiceConnections.values().iterator();
9240 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009241 ArrayList<ConnectionRecord> r = it.next();
9242 for (int i=0; i<r.size(); i++) {
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07009243 ConnectionRecord cr = r.get(i);
9244 if (!matcher.match(cr.binding.service, cr.binding.service.name)) {
9245 continue;
9246 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009247 if (dumpPackage != null && (cr.binding.client == null
9248 || !dumpPackage.equals(cr.binding.client.info.packageName))) {
9249 continue;
9250 }
9251 if (!printed) {
9252 if (needSep) pw.println(" ");
9253 needSep = true;
9254 pw.println(" Connection bindings to services:");
9255 printed = true;
9256 }
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07009257 pw.print(" * "); pw.println(cr);
9258 cr.dump(pw, " ");
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009259 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009260 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009261 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009262 }
9263 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009264
9265 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009266 }
9267
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009268 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009269 int opti, boolean dumpAll, String dumpPackage) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009270 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009271
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07009272 ItemMatcher matcher = new ItemMatcher();
9273 matcher.build(args, opti);
9274
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009275 pw.println("ACTIVITY MANAGER CONTENT PROVIDERS (dumpsys activity providers)");
9276 if (mProvidersByClass.size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009277 boolean printed = false;
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07009278 Iterator<Map.Entry<ComponentName, ContentProviderRecord>> it
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009279 = mProvidersByClass.entrySet().iterator();
9280 while (it.hasNext()) {
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07009281 Map.Entry<ComponentName, ContentProviderRecord> e = it.next();
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009282 ContentProviderRecord r = e.getValue();
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07009283 ComponentName comp = e.getKey();
9284 String cls = comp.getClassName();
9285 int end = cls.lastIndexOf('.');
9286 if (end > 0 && end < (cls.length()-2)) {
9287 cls = cls.substring(end+1);
9288 }
9289 if (!matcher.match(r, comp)) {
9290 continue;
9291 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009292 if (dumpPackage != null && !dumpPackage.equals(comp.getPackageName())) {
9293 continue;
9294 }
9295 if (!printed) {
9296 if (needSep) pw.println(" ");
9297 needSep = true;
9298 pw.println(" Published content providers (by class):");
9299 printed = true;
9300 }
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07009301 pw.print(" * "); pw.print(cls); pw.print(" (");
Dianne Hackborn8ec8d412011-11-14 18:27:24 -08009302 pw.print(comp.flattenToShortString()); pw.println(")");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009303 if (dumpAll) {
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07009304 r.dump(pw, " ");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009305 } else {
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07009306 if (r.proc != null) {
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07009307 pw.print(" "); pw.println(r.proc);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009308 } else {
9309 pw.println();
9310 }
Dianne Hackborn8ec8d412011-11-14 18:27:24 -08009311 if (r.clients.size() > 0) {
9312 pw.println(" Clients:");
9313 for (ProcessRecord cproc : r.clients) {
9314 pw.print(" - "); pw.println(cproc);
9315 }
9316 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009317 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009318 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009319 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009320
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009321 if (dumpAll) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009322 if (mProvidersByName.size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009323 boolean printed = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -07009324 Iterator<Map.Entry<String, ContentProviderRecord>> it
9325 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009326 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009327 Map.Entry<String, ContentProviderRecord> e = it.next();
9328 ContentProviderRecord r = e.getValue();
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07009329 if (!matcher.match(r, r.name)) {
9330 continue;
9331 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009332 if (dumpPackage != null && !dumpPackage.equals(r.name.getPackageName())) {
9333 continue;
9334 }
9335 if (!printed) {
9336 if (needSep) pw.println(" ");
9337 needSep = true;
9338 pw.println(" Authority to provider mappings:");
9339 printed = true;
9340 }
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -08009341 pw.print(" "); pw.print(e.getKey()); pw.println(":");
9342 pw.print(" "); pw.println(r);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009343 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009344 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009345 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009346
9347 if (mLaunchingProviders.size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009348 boolean printed = false;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009349 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009350 ContentProviderRecord r = mLaunchingProviders.get(i);
9351 if (dumpPackage != null && !dumpPackage.equals(r.name.getPackageName())) {
9352 continue;
9353 }
9354 if (!printed) {
9355 if (needSep) pw.println(" ");
9356 needSep = true;
9357 pw.println(" Launching content providers:");
9358 printed = true;
9359 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009360 pw.print(" Launching #"); pw.print(i); pw.print(": ");
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009361 pw.println(r);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009362 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009363 }
9364
9365 if (mGrantedUriPermissions.size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009366 if (needSep) pw.println();
9367 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009368 pw.println("Granted Uri Permissions:");
9369 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
9370 int uid = mGrantedUriPermissions.keyAt(i);
9371 HashMap<Uri, UriPermission> perms
9372 = mGrantedUriPermissions.valueAt(i);
9373 pw.print(" * UID "); pw.print(uid);
9374 pw.println(" holds:");
9375 for (UriPermission perm : perms.values()) {
9376 pw.print(" "); pw.println(perm);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009377 if (dumpAll) {
9378 perm.dump(pw, " ");
9379 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009380 }
9381 }
9382 needSep = true;
9383 }
9384
9385 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009386 }
9387
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009388 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009389 int opti, boolean dumpAll, String dumpPackage) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009390 boolean needSep = false;
9391
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009392 if (mIntentSenderRecords.size() > 0) {
9393 boolean printed = false;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009394 Iterator<WeakReference<PendingIntentRecord>> it
9395 = mIntentSenderRecords.values().iterator();
9396 while (it.hasNext()) {
9397 WeakReference<PendingIntentRecord> ref = it.next();
9398 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009399 if (dumpPackage != null && (rec == null
9400 || !dumpPackage.equals(rec.key.packageName))) {
9401 continue;
9402 }
9403 if (!printed) {
9404 pw.println("ACTIVITY MANAGER PENDING INTENTS (dumpsys activity intents)");
9405 printed = true;
9406 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009407 needSep = true;
9408 if (rec != null) {
9409 pw.print(" * "); pw.println(rec);
9410 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009411 rec.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009412 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009413 } else {
9414 pw.print(" * "); pw.println(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009415 }
9416 }
9417 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009418
9419 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009420 }
9421
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009422 private static final void dumpHistoryList(FileDescriptor fd, PrintWriter pw, List list,
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009423 String prefix, String label, boolean complete, boolean brief, boolean client,
9424 String dumpPackage) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009425 TaskRecord lastTask = null;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009426 boolean needNL = false;
9427 final String innerPrefix = prefix + " ";
9428 final String[] args = new String[0];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009429 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009430 final ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009431 if (dumpPackage != null && !dumpPackage.equals(r.packageName)) {
9432 continue;
9433 }
Dianne Hackbornf26fd992011-04-08 18:14:09 -07009434 final boolean full = !brief && (complete || !r.isInHistory());
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009435 if (needNL) {
9436 pw.println(" ");
9437 needNL = false;
9438 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009439 if (lastTask != r.task) {
9440 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009441 pw.print(prefix);
9442 pw.print(full ? "* " : " ");
9443 pw.println(lastTask);
9444 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009445 lastTask.dump(pw, prefix + " ");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009446 } else if (complete) {
9447 // Complete + brief == give a summary. Isn't that obvious?!?
9448 if (lastTask.intent != null) {
Dianne Hackborn90c52de2011-09-23 12:57:44 -07009449 pw.print(prefix); pw.print(" ");
9450 pw.println(lastTask.intent.toInsecureString());
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009451 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009452 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009453 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009454 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
9455 pw.print(" #"); pw.print(i); pw.print(": ");
9456 pw.println(r);
9457 if (full) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009458 r.dump(pw, innerPrefix);
9459 } else if (complete) {
9460 // Complete + brief == give a summary. Isn't that obvious?!?
Dianne Hackborn90c52de2011-09-23 12:57:44 -07009461 pw.print(innerPrefix); pw.println(r.intent.toInsecureString());
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009462 if (r.app != null) {
9463 pw.print(innerPrefix); pw.println(r.app);
9464 }
9465 }
9466 if (client && r.app != null && r.app.thread != null) {
9467 // flush anything that is already in the PrintWriter since the thread is going
9468 // to write to the file descriptor directly
9469 pw.flush();
9470 try {
9471 TransferPipe tp = new TransferPipe();
9472 try {
Dianne Hackbornbe707852011-11-11 14:32:10 -08009473 r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(),
9474 r.appToken, innerPrefix, args);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009475 // Short timeout, since blocking here can
9476 // deadlock with the application.
9477 tp.go(fd, 2000);
9478 } finally {
9479 tp.kill();
9480 }
9481 } catch (IOException e) {
9482 pw.println(innerPrefix + "Failure while dumping the activity: " + e);
9483 } catch (RemoteException e) {
9484 pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
9485 }
9486 needNL = true;
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009487 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009488 }
9489 }
9490
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009491 private static String buildOomTag(String prefix, String space, int val, int base) {
9492 if (val == base) {
9493 if (space == null) return prefix;
9494 return prefix + " ";
9495 }
9496 return prefix + "+" + Integer.toString(val-base);
9497 }
9498
9499 private static final int dumpProcessList(PrintWriter pw,
9500 ActivityManagerService service, List list,
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009501 String prefix, String normalLabel, String persistentLabel,
9502 String dumpPackage) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009503 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07009504 final int N = list.size()-1;
9505 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009506 ProcessRecord r = (ProcessRecord)list.get(i);
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009507 if (dumpPackage != null && !dumpPackage.equals(r.info.packageName)) {
9508 continue;
9509 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07009510 pw.println(String.format("%s%s #%2d: %s",
9511 prefix, (r.persistent ? persistentLabel : normalLabel),
9512 i, r.toString()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009513 if (r.persistent) {
9514 numPers++;
9515 }
9516 }
9517 return numPers;
9518 }
9519
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009520 private static final boolean dumpProcessOomList(PrintWriter pw,
Dianne Hackborn905577f2011-09-07 18:31:28 -07009521 ActivityManagerService service, List<ProcessRecord> origList,
Dianne Hackborn287952c2010-09-22 22:34:31 -07009522 String prefix, String normalLabel, String persistentLabel,
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009523 boolean inclDetails, String dumpPackage) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009524
Dianne Hackborn905577f2011-09-07 18:31:28 -07009525 ArrayList<Pair<ProcessRecord, Integer>> list
9526 = new ArrayList<Pair<ProcessRecord, Integer>>(origList.size());
9527 for (int i=0; i<origList.size(); i++) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009528 ProcessRecord r = origList.get(i);
9529 if (dumpPackage != null && !dumpPackage.equals(r.info.packageName)) {
9530 continue;
9531 }
Dianne Hackborn905577f2011-09-07 18:31:28 -07009532 list.add(new Pair<ProcessRecord, Integer>(origList.get(i), i));
9533 }
9534
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009535 if (list.size() <= 0) {
9536 return false;
9537 }
9538
Dianne Hackborn905577f2011-09-07 18:31:28 -07009539 Comparator<Pair<ProcessRecord, Integer>> comparator
9540 = new Comparator<Pair<ProcessRecord, Integer>>() {
9541 @Override
9542 public int compare(Pair<ProcessRecord, Integer> object1,
9543 Pair<ProcessRecord, Integer> object2) {
9544 if (object1.first.setAdj != object2.first.setAdj) {
9545 return object1.first.setAdj > object2.first.setAdj ? -1 : 1;
9546 }
9547 if (object1.second.intValue() != object2.second.intValue()) {
9548 return object1.second.intValue() > object2.second.intValue() ? -1 : 1;
9549 }
9550 return 0;
9551 }
9552 };
9553
9554 Collections.sort(list, comparator);
9555
Dianne Hackborn287952c2010-09-22 22:34:31 -07009556 final long curRealtime = SystemClock.elapsedRealtime();
9557 final long realtimeSince = curRealtime - service.mLastPowerCheckRealtime;
9558 final long curUptime = SystemClock.uptimeMillis();
9559 final long uptimeSince = curUptime - service.mLastPowerCheckUptime;
9560
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009561 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborn905577f2011-09-07 18:31:28 -07009562 ProcessRecord r = list.get(i).first;
Dianne Hackborn287952c2010-09-22 22:34:31 -07009563 String oomAdj;
Dianne Hackborne02c88a2011-10-28 13:58:15 -07009564 if (r.setAdj >= ProcessList.HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn7d608422011-08-07 16:24:18 -07009565 oomAdj = buildOomTag("bak", " ", r.setAdj, ProcessList.HIDDEN_APP_MIN_ADJ);
Dianne Hackborne02c88a2011-10-28 13:58:15 -07009566 } else if (r.setAdj >= ProcessList.SERVICE_B_ADJ) {
9567 oomAdj = buildOomTag("svcb ", null, r.setAdj, ProcessList.SERVICE_B_ADJ);
Dianne Hackbornf35fe232011-11-01 19:25:20 -07009568 } else if (r.setAdj >= ProcessList.PREVIOUS_APP_ADJ) {
9569 oomAdj = buildOomTag("prev ", null, r.setAdj, ProcessList.PREVIOUS_APP_ADJ);
Dianne Hackborn7d608422011-08-07 16:24:18 -07009570 } else if (r.setAdj >= ProcessList.HOME_APP_ADJ) {
9571 oomAdj = buildOomTag("home ", null, r.setAdj, ProcessList.HOME_APP_ADJ);
Dianne Hackborne02c88a2011-10-28 13:58:15 -07009572 } else if (r.setAdj >= ProcessList.SERVICE_ADJ) {
9573 oomAdj = buildOomTag("svc ", null, r.setAdj, ProcessList.SERVICE_ADJ);
Dianne Hackborn7d608422011-08-07 16:24:18 -07009574 } else if (r.setAdj >= ProcessList.BACKUP_APP_ADJ) {
Dianne Hackborn672342c2011-11-29 11:29:02 -08009575 oomAdj = buildOomTag("bkup ", null, r.setAdj, ProcessList.BACKUP_APP_ADJ);
Dianne Hackborn7d608422011-08-07 16:24:18 -07009576 } else if (r.setAdj >= ProcessList.HEAVY_WEIGHT_APP_ADJ) {
9577 oomAdj = buildOomTag("hvy ", null, r.setAdj, ProcessList.HEAVY_WEIGHT_APP_ADJ);
9578 } else if (r.setAdj >= ProcessList.PERCEPTIBLE_APP_ADJ) {
9579 oomAdj = buildOomTag("prcp ", null, r.setAdj, ProcessList.PERCEPTIBLE_APP_ADJ);
9580 } else if (r.setAdj >= ProcessList.VISIBLE_APP_ADJ) {
9581 oomAdj = buildOomTag("vis ", null, r.setAdj, ProcessList.VISIBLE_APP_ADJ);
9582 } else if (r.setAdj >= ProcessList.FOREGROUND_APP_ADJ) {
9583 oomAdj = buildOomTag("fore ", null, r.setAdj, ProcessList.FOREGROUND_APP_ADJ);
Dianne Hackborne02c88a2011-10-28 13:58:15 -07009584 } else if (r.setAdj >= ProcessList.PERSISTENT_PROC_ADJ) {
9585 oomAdj = buildOomTag("pers ", null, r.setAdj, ProcessList.PERSISTENT_PROC_ADJ);
Dianne Hackborn7d608422011-08-07 16:24:18 -07009586 } else if (r.setAdj >= ProcessList.SYSTEM_ADJ) {
9587 oomAdj = buildOomTag("sys ", null, r.setAdj, ProcessList.SYSTEM_ADJ);
Dianne Hackborn287952c2010-09-22 22:34:31 -07009588 } else {
9589 oomAdj = Integer.toString(r.setAdj);
9590 }
9591 String schedGroup;
9592 switch (r.setSchedGroup) {
9593 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
9594 schedGroup = "B";
9595 break;
9596 case Process.THREAD_GROUP_DEFAULT:
9597 schedGroup = "F";
9598 break;
9599 default:
9600 schedGroup = Integer.toString(r.setSchedGroup);
9601 break;
9602 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07009603 String foreground;
9604 if (r.foregroundActivities) {
9605 foreground = "A";
9606 } else if (r.foregroundServices) {
9607 foreground = "S";
9608 } else {
9609 foreground = " ";
9610 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -07009611 pw.println(String.format("%s%s #%2d: adj=%s/%s%s trm=%2d %s (%s)",
Dianne Hackborn287952c2010-09-22 22:34:31 -07009612 prefix, (r.persistent ? persistentLabel : normalLabel),
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009613 (origList.size()-1)-list.get(i).second, oomAdj, schedGroup,
9614 foreground, r.trimMemoryLevel, r.toShortString(), r.adjType));
Dianne Hackborn287952c2010-09-22 22:34:31 -07009615 if (r.adjSource != null || r.adjTarget != null) {
9616 pw.print(prefix);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009617 pw.print(" ");
Dianne Hackborn287952c2010-09-22 22:34:31 -07009618 if (r.adjTarget instanceof ComponentName) {
9619 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
9620 } else if (r.adjTarget != null) {
9621 pw.print(r.adjTarget.toString());
9622 } else {
9623 pw.print("{null}");
9624 }
9625 pw.print("<=");
9626 if (r.adjSource instanceof ProcessRecord) {
9627 pw.print("Proc{");
9628 pw.print(((ProcessRecord)r.adjSource).toShortString());
9629 pw.println("}");
9630 } else if (r.adjSource != null) {
9631 pw.println(r.adjSource.toString());
9632 } else {
9633 pw.println("{null}");
9634 }
9635 }
9636 if (inclDetails) {
9637 pw.print(prefix);
9638 pw.print(" ");
9639 pw.print("oom: max="); pw.print(r.maxAdj);
9640 pw.print(" hidden="); pw.print(r.hiddenAdj);
9641 pw.print(" curRaw="); pw.print(r.curRawAdj);
9642 pw.print(" setRaw="); pw.print(r.setRawAdj);
9643 pw.print(" cur="); pw.print(r.curAdj);
9644 pw.print(" set="); pw.println(r.setAdj);
9645 pw.print(prefix);
9646 pw.print(" ");
9647 pw.print("keeping="); pw.print(r.keeping);
9648 pw.print(" hidden="); pw.print(r.hidden);
Dianne Hackbornc68c9132011-07-29 01:25:18 -07009649 pw.print(" empty="); pw.print(r.empty);
9650 pw.print(" hasAboveClient="); pw.println(r.hasAboveClient);
Dianne Hackborn287952c2010-09-22 22:34:31 -07009651
9652 if (!r.keeping) {
9653 if (r.lastWakeTime != 0) {
9654 long wtime;
9655 BatteryStatsImpl stats = service.mBatteryStatsService.getActiveStatistics();
9656 synchronized (stats) {
9657 wtime = stats.getProcessWakeTime(r.info.uid,
9658 r.pid, curRealtime);
9659 }
9660 long timeUsed = wtime - r.lastWakeTime;
9661 pw.print(prefix);
9662 pw.print(" ");
9663 pw.print("keep awake over ");
9664 TimeUtils.formatDuration(realtimeSince, pw);
9665 pw.print(" used ");
9666 TimeUtils.formatDuration(timeUsed, pw);
9667 pw.print(" (");
9668 pw.print((timeUsed*100)/realtimeSince);
9669 pw.println("%)");
9670 }
9671 if (r.lastCpuTime != 0) {
9672 long timeUsed = r.curCpuTime - r.lastCpuTime;
9673 pw.print(prefix);
9674 pw.print(" ");
9675 pw.print("run cpu over ");
9676 TimeUtils.formatDuration(uptimeSince, pw);
9677 pw.print(" used ");
9678 TimeUtils.formatDuration(timeUsed, pw);
9679 pw.print(" (");
9680 pw.print((timeUsed*100)/uptimeSince);
9681 pw.println("%)");
9682 }
9683 }
9684 }
9685 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009686 return true;
Dianne Hackborn287952c2010-09-22 22:34:31 -07009687 }
9688
Dianne Hackbornb437e092011-08-05 17:50:29 -07009689 ArrayList<ProcessRecord> collectProcesses(PrintWriter pw, int start, String[] args) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009690 ArrayList<ProcessRecord> procs;
9691 synchronized (this) {
Dianne Hackbornb437e092011-08-05 17:50:29 -07009692 if (args != null && args.length > start
9693 && args[start].charAt(0) != '-') {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009694 procs = new ArrayList<ProcessRecord>();
9695 int pid = -1;
9696 try {
Dianne Hackbornb437e092011-08-05 17:50:29 -07009697 pid = Integer.parseInt(args[start]);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009698 } catch (NumberFormatException e) {
9699
9700 }
9701 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9702 ProcessRecord proc = mLruProcesses.get(i);
9703 if (proc.pid == pid) {
9704 procs.add(proc);
Dianne Hackbornb437e092011-08-05 17:50:29 -07009705 } else if (proc.processName.equals(args[start])) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009706 procs.add(proc);
9707 }
9708 }
9709 if (procs.size() <= 0) {
Dianne Hackbornb437e092011-08-05 17:50:29 -07009710 pw.println("No process found for: " + args[start]);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009711 return null;
9712 }
9713 } else {
9714 procs = new ArrayList<ProcessRecord>(mLruProcesses);
9715 }
9716 }
9717 return procs;
9718 }
9719
9720 final void dumpGraphicsHardwareUsage(FileDescriptor fd,
9721 PrintWriter pw, String[] args) {
Dianne Hackbornb437e092011-08-05 17:50:29 -07009722 ArrayList<ProcessRecord> procs = collectProcesses(pw, 0, args);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009723 if (procs == null) {
9724 return;
9725 }
9726
9727 long uptime = SystemClock.uptimeMillis();
9728 long realtime = SystemClock.elapsedRealtime();
9729 pw.println("Applications Graphics Acceleration Info:");
9730 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
9731
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009732 for (int i = procs.size() - 1 ; i >= 0 ; i--) {
9733 ProcessRecord r = procs.get(i);
Chet Haase9c1e23b2011-03-24 10:51:31 -07009734 if (r.thread != null) {
9735 pw.println("\n** Graphics info for pid " + r.pid + " [" + r.processName + "] **");
9736 pw.flush();
9737 try {
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009738 TransferPipe tp = new TransferPipe();
9739 try {
9740 r.thread.dumpGfxInfo(tp.getWriteFd().getFileDescriptor(), args);
9741 tp.go(fd);
9742 } finally {
9743 tp.kill();
9744 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009745 } catch (IOException e) {
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009746 pw.println("Failure while dumping the app: " + r);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009747 pw.flush();
Chet Haase9c1e23b2011-03-24 10:51:31 -07009748 } catch (RemoteException e) {
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009749 pw.println("Got a RemoteException while dumping the app " + r);
Chet Haase9c1e23b2011-03-24 10:51:31 -07009750 pw.flush();
9751 }
9752 }
9753 }
Chet Haase9c1e23b2011-03-24 10:51:31 -07009754 }
9755
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009756 final static class MemItem {
9757 final String label;
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -08009758 final String shortLabel;
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009759 final long pss;
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -08009760 final int id;
Dianne Hackborna4bacb82011-08-24 15:12:38 -07009761 ArrayList<MemItem> subitems;
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009762
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -08009763 public MemItem(String _label, String _shortLabel, long _pss, int _id) {
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009764 label = _label;
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -08009765 shortLabel = _shortLabel;
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009766 pss = _pss;
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -08009767 id = _id;
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009768 }
9769 }
9770
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -08009771 static final void dumpMemItems(PrintWriter pw, String prefix, ArrayList<MemItem> items,
Dianne Hackbornb437e092011-08-05 17:50:29 -07009772 boolean sort) {
9773 if (sort) {
9774 Collections.sort(items, new Comparator<MemItem>() {
9775 @Override
9776 public int compare(MemItem lhs, MemItem rhs) {
9777 if (lhs.pss < rhs.pss) {
9778 return 1;
9779 } else if (lhs.pss > rhs.pss) {
9780 return -1;
9781 }
9782 return 0;
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009783 }
Dianne Hackbornb437e092011-08-05 17:50:29 -07009784 });
9785 }
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009786
9787 for (int i=0; i<items.size(); i++) {
9788 MemItem mi = items.get(i);
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -08009789 pw.print(prefix); pw.printf("%7d kB: ", mi.pss); pw.println(mi.label);
Dianne Hackborna4bacb82011-08-24 15:12:38 -07009790 if (mi.subitems != null) {
9791 dumpMemItems(pw, prefix + " ", mi.subitems, true);
9792 }
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009793 }
9794 }
9795
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -08009796 // These are in KB.
9797 static final long[] DUMP_MEM_BUCKETS = new long[] {
9798 5*1024, 7*1024, 10*1024, 15*1024, 20*1024, 30*1024, 40*1024, 80*1024,
9799 120*1024, 160*1024, 200*1024,
9800 250*1024, 300*1024, 350*1024, 400*1024, 500*1024, 600*1024, 800*1024,
9801 1*1024*1024, 2*1024*1024, 5*1024*1024, 10*1024*1024, 20*1024*1024
9802 };
9803
Dianne Hackborn672342c2011-11-29 11:29:02 -08009804 static final void appendMemBucket(StringBuilder out, long memKB, String label,
9805 boolean stackLike) {
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -08009806 int start = label.lastIndexOf('.');
9807 if (start >= 0) start++;
9808 else start = 0;
9809 int end = label.length();
9810 for (int i=0; i<DUMP_MEM_BUCKETS.length; i++) {
9811 if (DUMP_MEM_BUCKETS[i] >= memKB) {
9812 long bucket = DUMP_MEM_BUCKETS[i]/1024;
9813 out.append(bucket);
Dianne Hackborn672342c2011-11-29 11:29:02 -08009814 out.append(stackLike ? "MB." : "MB ");
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -08009815 out.append(label, start, end);
9816 return;
9817 }
9818 }
9819 out.append(memKB/1024);
Dianne Hackborn672342c2011-11-29 11:29:02 -08009820 out.append(stackLike ? "MB." : "MB ");
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -08009821 out.append(label, start, end);
9822 }
9823
9824 static final int[] DUMP_MEM_OOM_ADJ = new int[] {
9825 ProcessList.SYSTEM_ADJ, ProcessList.PERSISTENT_PROC_ADJ, ProcessList.FOREGROUND_APP_ADJ,
9826 ProcessList.VISIBLE_APP_ADJ, ProcessList.PERCEPTIBLE_APP_ADJ, ProcessList.HEAVY_WEIGHT_APP_ADJ,
9827 ProcessList.BACKUP_APP_ADJ, ProcessList.SERVICE_ADJ, ProcessList.HOME_APP_ADJ,
9828 ProcessList.PREVIOUS_APP_ADJ, ProcessList.SERVICE_B_ADJ, ProcessList.HIDDEN_APP_MAX_ADJ
9829 };
9830 static final String[] DUMP_MEM_OOM_LABEL = new String[] {
9831 "System", "Persistent", "Foreground",
9832 "Visible", "Perceptible", "Heavy Weight",
9833 "Backup", "A Services", "Home", "Previous",
9834 "B Services", "Background"
9835 };
9836
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009837 final void dumpApplicationMemoryUsage(FileDescriptor fd,
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08009838 PrintWriter pw, String prefix, String[] args, boolean brief,
Dianne Hackborn672342c2011-11-29 11:29:02 -08009839 PrintWriter categoryPw, StringBuilder outTag, StringBuilder outStack) {
Dianne Hackbornb437e092011-08-05 17:50:29 -07009840 boolean dumpAll = false;
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08009841 boolean oomOnly = false;
Dianne Hackbornb437e092011-08-05 17:50:29 -07009842
9843 int opti = 0;
9844 while (opti < args.length) {
9845 String opt = args[opti];
9846 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
9847 break;
9848 }
9849 opti++;
9850 if ("-a".equals(opt)) {
9851 dumpAll = true;
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08009852 } else if ("--oom".equals(opt)) {
9853 oomOnly = true;
Dianne Hackbornb437e092011-08-05 17:50:29 -07009854 } else if ("-h".equals(opt)) {
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08009855 pw.println("meminfo dump options: [-a] [--oom] [process]");
Dianne Hackbornb437e092011-08-05 17:50:29 -07009856 pw.println(" -a: include all available information for each process.");
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08009857 pw.println(" --oom: only show processes organized by oom adj.");
Dianne Hackbornb437e092011-08-05 17:50:29 -07009858 pw.println("If [process] is specified it can be the name or ");
9859 pw.println("pid of a specific process to dump.");
9860 return;
9861 } else {
9862 pw.println("Unknown argument: " + opt + "; use -h for help");
9863 }
9864 }
9865
9866 ArrayList<ProcessRecord> procs = collectProcesses(pw, opti, args);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009867 if (procs == null) {
9868 return;
9869 }
9870
Dianne Hackborn6447ca32009-04-07 19:50:08 -07009871 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009872 long uptime = SystemClock.uptimeMillis();
9873 long realtime = SystemClock.elapsedRealtime();
Dianne Hackbornb437e092011-08-05 17:50:29 -07009874
9875 if (procs.size() == 1 || isCheckinRequest) {
9876 dumpAll = true;
9877 }
9878
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009879 if (isCheckinRequest) {
9880 // short checkin version
9881 pw.println(uptime + "," + realtime);
9882 pw.flush();
9883 } else {
9884 pw.println("Applications Memory Usage (kB):");
9885 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
9886 }
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009887
Dianne Hackbornb437e092011-08-05 17:50:29 -07009888 String[] innerArgs = new String[args.length-opti];
9889 System.arraycopy(args, opti, innerArgs, 0, args.length-opti);
9890
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009891 ArrayList<MemItem> procMems = new ArrayList<MemItem>();
9892 long nativePss=0, dalvikPss=0, otherPss=0;
9893 long[] miscPss = new long[Debug.MemoryInfo.NUM_OTHER_STATS];
9894
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -08009895 long oomPss[] = new long[DUMP_MEM_OOM_LABEL.length];
9896 ArrayList<MemItem>[] oomProcs = (ArrayList<MemItem>[])
9897 new ArrayList[DUMP_MEM_OOM_LABEL.length];
Dianne Hackbornb437e092011-08-05 17:50:29 -07009898
9899 long totalPss = 0;
9900
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009901 for (int i = procs.size() - 1 ; i >= 0 ; i--) {
9902 ProcessRecord r = procs.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009903 if (r.thread != null) {
Dianne Hackbornb437e092011-08-05 17:50:29 -07009904 if (!isCheckinRequest && dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009905 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
9906 pw.flush();
9907 }
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009908 Debug.MemoryInfo mi = null;
Dianne Hackbornb437e092011-08-05 17:50:29 -07009909 if (dumpAll) {
9910 try {
9911 mi = r.thread.dumpMemInfo(fd, isCheckinRequest, dumpAll, innerArgs);
9912 } catch (RemoteException e) {
9913 if (!isCheckinRequest) {
9914 pw.println("Got RemoteException!");
9915 pw.flush();
9916 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009917 }
Dianne Hackbornb437e092011-08-05 17:50:29 -07009918 } else {
9919 mi = new Debug.MemoryInfo();
9920 Debug.getMemoryInfo(r.pid, mi);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009921 }
Dianne Hackbornb437e092011-08-05 17:50:29 -07009922
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009923 if (!isCheckinRequest && mi != null) {
Dianne Hackbornb437e092011-08-05 17:50:29 -07009924 long myTotalPss = mi.getTotalPss();
9925 totalPss += myTotalPss;
Dianne Hackborna4bacb82011-08-24 15:12:38 -07009926 MemItem pssItem = new MemItem(r.processName + " (pid " + r.pid + ")",
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -08009927 r.processName, myTotalPss, 0);
Dianne Hackborna4bacb82011-08-24 15:12:38 -07009928 procMems.add(pssItem);
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009929
9930 nativePss += mi.nativePss;
9931 dalvikPss += mi.dalvikPss;
9932 otherPss += mi.otherPss;
9933 for (int j=0; j<Debug.MemoryInfo.NUM_OTHER_STATS; j++) {
9934 long mem = mi.getOtherPss(j);
9935 miscPss[j] += mem;
9936 otherPss -= mem;
9937 }
Dianne Hackbornb437e092011-08-05 17:50:29 -07009938
9939 for (int oomIndex=0; oomIndex<oomPss.length; oomIndex++) {
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -08009940 if (r.setAdj <= DUMP_MEM_OOM_ADJ[oomIndex]
9941 || oomIndex == (oomPss.length-1)) {
Dianne Hackbornb437e092011-08-05 17:50:29 -07009942 oomPss[oomIndex] += myTotalPss;
Dianne Hackborna4bacb82011-08-24 15:12:38 -07009943 if (oomProcs[oomIndex] == null) {
9944 oomProcs[oomIndex] = new ArrayList<MemItem>();
9945 }
9946 oomProcs[oomIndex].add(pssItem);
Dianne Hackbornb437e092011-08-05 17:50:29 -07009947 break;
9948 }
9949 }
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009950 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009951 }
9952 }
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009953
9954 if (!isCheckinRequest && procs.size() > 1) {
9955 ArrayList<MemItem> catMems = new ArrayList<MemItem>();
9956
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -08009957 catMems.add(new MemItem("Native", "Native", nativePss, -1));
9958 catMems.add(new MemItem("Dalvik", "Dalvik", dalvikPss, -2));
9959 catMems.add(new MemItem("Unknown", "Unknown", otherPss, -3));
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009960 for (int j=0; j<Debug.MemoryInfo.NUM_OTHER_STATS; j++) {
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -08009961 String label = Debug.MemoryInfo.getOtherLabel(j);
9962 catMems.add(new MemItem(label, label, miscPss[j], j));
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009963 }
9964
Dianne Hackbornb437e092011-08-05 17:50:29 -07009965 ArrayList<MemItem> oomMems = new ArrayList<MemItem>();
9966 for (int j=0; j<oomPss.length; j++) {
9967 if (oomPss[j] != 0) {
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -08009968 String label = DUMP_MEM_OOM_LABEL[j];
9969 MemItem item = new MemItem(label, label, oomPss[j],
9970 DUMP_MEM_OOM_ADJ[j]);
Dianne Hackborna4bacb82011-08-24 15:12:38 -07009971 item.subitems = oomProcs[j];
9972 oomMems.add(item);
Dianne Hackbornb437e092011-08-05 17:50:29 -07009973 }
9974 }
9975
Dianne Hackborn672342c2011-11-29 11:29:02 -08009976 if (outTag != null || outStack != null) {
9977 if (outTag != null) {
9978 appendMemBucket(outTag, totalPss, "total", false);
9979 }
9980 if (outStack != null) {
9981 appendMemBucket(outStack, totalPss, "total", true);
9982 }
9983 boolean firstLine = true;
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -08009984 for (int i=0; i<oomMems.size(); i++) {
9985 MemItem miCat = oomMems.get(i);
9986 if (miCat.subitems == null || miCat.subitems.size() < 1) {
9987 continue;
9988 }
9989 if (miCat.id < ProcessList.SERVICE_ADJ
9990 || miCat.id == ProcessList.HOME_APP_ADJ
9991 || miCat.id == ProcessList.PREVIOUS_APP_ADJ) {
Dianne Hackborn672342c2011-11-29 11:29:02 -08009992 if (outTag != null && miCat.id <= ProcessList.FOREGROUND_APP_ADJ) {
9993 outTag.append(" / ");
9994 }
9995 if (outStack != null) {
9996 if (miCat.id >= ProcessList.FOREGROUND_APP_ADJ) {
9997 if (firstLine) {
9998 outStack.append(":");
9999 firstLine = false;
10000 }
10001 outStack.append("\n\t at ");
10002 } else {
10003 outStack.append("$");
10004 }
10005 }
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010006 for (int j=0; j<miCat.subitems.size(); j++) {
10007 MemItem mi = miCat.subitems.get(j);
10008 if (j > 0) {
Dianne Hackborn672342c2011-11-29 11:29:02 -080010009 if (outTag != null) {
10010 outTag.append(" ");
10011 }
10012 if (outStack != null) {
10013 outStack.append("$");
10014 }
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010015 }
Dianne Hackborn672342c2011-11-29 11:29:02 -080010016 if (outTag != null && miCat.id <= ProcessList.FOREGROUND_APP_ADJ) {
10017 appendMemBucket(outTag, mi.pss, mi.shortLabel, false);
10018 }
10019 if (outStack != null) {
10020 appendMemBucket(outStack, mi.pss, mi.shortLabel, true);
10021 }
10022 }
10023 if (outStack != null && miCat.id >= ProcessList.FOREGROUND_APP_ADJ) {
10024 outStack.append("(");
10025 for (int k=0; k<DUMP_MEM_OOM_ADJ.length; k++) {
10026 if (DUMP_MEM_OOM_ADJ[k] == miCat.id) {
10027 outStack.append(DUMP_MEM_OOM_LABEL[k]);
10028 outStack.append(":");
10029 outStack.append(DUMP_MEM_OOM_ADJ[k]);
10030 }
10031 }
10032 outStack.append(")");
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010033 }
10034 }
10035 }
10036 }
10037
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -080010038 if (!brief && !oomOnly) {
Dianne Hackborn04d6db32011-11-04 20:07:24 -070010039 pw.println();
10040 pw.println("Total PSS by process:");
10041 dumpMemItems(pw, " ", procMems, true);
10042 pw.println();
10043 }
Dianne Hackbornb437e092011-08-05 17:50:29 -070010044 pw.println("Total PSS by OOM adjustment:");
10045 dumpMemItems(pw, " ", oomMems, false);
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -080010046 if (!oomOnly) {
10047 PrintWriter out = categoryPw != null ? categoryPw : pw;
10048 out.println();
10049 out.println("Total PSS by category:");
10050 dumpMemItems(out, " ", catMems, true);
Dianne Hackborn04d6db32011-11-04 20:07:24 -070010051 }
Dianne Hackbornb437e092011-08-05 17:50:29 -070010052 pw.println();
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010053 pw.print("Total PSS: "); pw.print(totalPss); pw.println(" kB");
Dianne Hackborn0e3328f2011-07-17 13:31:17 -070010054 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010055 }
10056
10057 /**
10058 * Searches array of arguments for the specified string
10059 * @param args array of argument strings
10060 * @param value value to search for
10061 * @return true if the value is contained in the array
10062 */
10063 private static boolean scanArgs(String[] args, String value) {
10064 if (args != null) {
10065 for (String arg : args) {
10066 if (value.equals(arg)) {
10067 return true;
10068 }
10069 }
10070 }
10071 return false;
10072 }
10073
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010074 private final void killServicesLocked(ProcessRecord app,
10075 boolean allowRestart) {
10076 // Report disconnected services.
10077 if (false) {
10078 // XXX we are letting the client link to the service for
10079 // death notifications.
10080 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010081 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010082 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010083 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010084 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010085 Iterator<ArrayList<ConnectionRecord>> jt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010086 = r.connections.values().iterator();
10087 while (jt.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010088 ArrayList<ConnectionRecord> cl = jt.next();
10089 for (int i=0; i<cl.size(); i++) {
10090 ConnectionRecord c = cl.get(i);
10091 if (c.binding.client != app) {
10092 try {
10093 //c.conn.connected(r.className, null);
10094 } catch (Exception e) {
10095 // todo: this should be asynchronous!
10096 Slog.w(TAG, "Exception thrown disconnected servce "
10097 + r.shortName
10098 + " from app " + app.processName, e);
10099 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010100 }
10101 }
10102 }
10103 }
10104 }
10105 }
10106 }
10107
10108 // Clean up any connections this application has to other services.
10109 if (app.connections.size() > 0) {
10110 Iterator<ConnectionRecord> it = app.connections.iterator();
10111 while (it.hasNext()) {
10112 ConnectionRecord r = it.next();
10113 removeConnectionLocked(r, app, null);
10114 }
10115 }
10116 app.connections.clear();
10117
10118 if (app.services.size() != 0) {
10119 // Any services running in the application need to be placed
10120 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -070010121 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010122 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010123 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010124 synchronized (sr.stats.getBatteryStats()) {
10125 sr.stats.stopLaunchedLocked();
10126 }
10127 sr.app = null;
10128 sr.executeNesting = 0;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010129 if (mStoppingServices.remove(sr)) {
10130 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
10131 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010132
10133 boolean hasClients = sr.bindings.size() > 0;
10134 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010135 Iterator<IntentBindRecord> bindings
10136 = sr.bindings.values().iterator();
10137 while (bindings.hasNext()) {
10138 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010139 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010140 + ": shouldUnbind=" + b.hasBound);
10141 b.binder = null;
10142 b.requested = b.received = b.hasBound = false;
10143 }
10144 }
10145
Dianne Hackborn070783f2010-12-29 16:46:28 -080010146 if (sr.crashCount >= 2 && (sr.serviceInfo.applicationInfo.flags
10147 &ApplicationInfo.FLAG_PERSISTENT) == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010148 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010149 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010150 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010151 sr.crashCount, sr.shortName, app.pid);
10152 bringDownServiceLocked(sr, true);
10153 } else if (!allowRestart) {
10154 bringDownServiceLocked(sr, true);
10155 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010156 boolean canceled = scheduleServiceRestartLocked(sr, true);
10157
10158 // Should the service remain running? Note that in the
10159 // extreme case of so many attempts to deliver a command
Dianne Hackborn130b0d22011-07-26 22:07:48 -070010160 // that it failed we also will stop it here.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010161 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
10162 if (sr.pendingStarts.size() == 0) {
10163 sr.startRequested = false;
10164 if (!hasClients) {
10165 // Whoops, no reason to restart!
10166 bringDownServiceLocked(sr, true);
10167 }
10168 }
10169 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010170 }
10171 }
10172
10173 if (!allowRestart) {
10174 app.services.clear();
10175 }
10176 }
10177
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010178 // Make sure we have no more records on the stopping list.
10179 int i = mStoppingServices.size();
10180 while (i > 0) {
10181 i--;
10182 ServiceRecord sr = mStoppingServices.get(i);
10183 if (sr.app == app) {
10184 mStoppingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010185 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010186 }
10187 }
10188
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010189 app.executingServices.clear();
10190 }
10191
10192 private final void removeDyingProviderLocked(ProcessRecord proc,
10193 ContentProviderRecord cpr) {
10194 synchronized (cpr) {
10195 cpr.launchingApp = null;
10196 cpr.notifyAll();
10197 }
10198
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -070010199 mProvidersByClass.remove(cpr.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010200 String names[] = cpr.info.authority.split(";");
10201 for (int j = 0; j < names.length; j++) {
10202 mProvidersByName.remove(names[j]);
10203 }
10204
10205 Iterator<ProcessRecord> cit = cpr.clients.iterator();
10206 while (cit.hasNext()) {
10207 ProcessRecord capp = cit.next();
10208 if (!capp.persistent && capp.thread != null
10209 && capp.pid != 0
10210 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -070010211 Slog.i(TAG, "Kill " + capp.processName
10212 + " (pid " + capp.pid + "): provider " + cpr.info.name
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -070010213 + " in dying process " + (proc != null ? proc.processName : "??"));
Dianne Hackborn8633e682010-04-22 16:03:41 -070010214 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -070010215 capp.processName, capp.setAdj, "dying provider "
10216 + cpr.name.toShortString());
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010217 Process.killProcessQuiet(capp.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010218 }
10219 }
10220
10221 mLaunchingProviders.remove(cpr);
10222 }
10223
10224 /**
10225 * Main code for cleaning up a process when it has gone away. This is
10226 * called both as a result of the process dying, or directly when stopping
10227 * a process when running in single process mode.
10228 */
10229 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
Dianne Hackborn130b0d22011-07-26 22:07:48 -070010230 boolean restarting, boolean allowRestart, int index) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010231 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010232 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010233 }
10234
Dianne Hackborn36124872009-10-08 16:22:03 -070010235 mProcessesToGc.remove(app);
10236
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010237 // Dismiss any open dialogs.
10238 if (app.crashDialog != null) {
10239 app.crashDialog.dismiss();
10240 app.crashDialog = null;
10241 }
10242 if (app.anrDialog != null) {
10243 app.anrDialog.dismiss();
10244 app.anrDialog = null;
10245 }
10246 if (app.waitDialog != null) {
10247 app.waitDialog.dismiss();
10248 app.waitDialog = null;
10249 }
10250
10251 app.crashing = false;
10252 app.notResponding = false;
10253
10254 app.resetPackageList();
Dianne Hackborn1b64e0d2011-07-17 15:23:59 -070010255 app.unlinkDeathRecipient();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010256 app.thread = null;
10257 app.forcingToForeground = null;
10258 app.foregroundServices = false;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070010259 app.foregroundActivities = false;
Dianne Hackbornf0754f5b2011-07-21 16:02:07 -070010260 app.hasShownUi = false;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070010261 app.hasAboveClient = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010262
Dianne Hackborn130b0d22011-07-26 22:07:48 -070010263 killServicesLocked(app, allowRestart);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010264
10265 boolean restart = false;
10266
10267 int NL = mLaunchingProviders.size();
10268
10269 // Remove published content providers.
10270 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010271 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010272 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010273 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010274 cpr.provider = null;
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -070010275 cpr.proc = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010276
10277 // See if someone is waiting for this provider... in which
10278 // case we don't remove it, but just let it restart.
10279 int i = 0;
Dianne Hackborn130b0d22011-07-26 22:07:48 -070010280 if (!app.bad && allowRestart) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010281 for (; i<NL; i++) {
10282 if (mLaunchingProviders.get(i) == cpr) {
10283 restart = true;
10284 break;
10285 }
10286 }
10287 } else {
10288 i = NL;
10289 }
10290
10291 if (i >= NL) {
10292 removeDyingProviderLocked(app, cpr);
10293 NL = mLaunchingProviders.size();
10294 }
10295 }
10296 app.pubProviders.clear();
10297 }
10298
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010299 // Take care of any launching providers waiting for this process.
10300 if (checkAppInLaunchingProvidersLocked(app, false)) {
10301 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010302 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010303
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010304 // Unregister from connected content providers.
10305 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -070010306 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010307 while (it.hasNext()) {
10308 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
10309 cpr.clients.remove(app);
10310 }
10311 app.conProviders.clear();
10312 }
10313
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010314 // At this point there may be remaining entries in mLaunchingProviders
10315 // where we were the only one waiting, so they are no longer of use.
10316 // Look for these and clean up if found.
10317 // XXX Commented out for now. Trying to figure out a way to reproduce
10318 // the actual situation to identify what is actually going on.
10319 if (false) {
10320 for (int i=0; i<NL; i++) {
10321 ContentProviderRecord cpr = (ContentProviderRecord)
10322 mLaunchingProviders.get(i);
10323 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
10324 synchronized (cpr) {
10325 cpr.launchingApp = null;
10326 cpr.notifyAll();
10327 }
10328 }
10329 }
10330 }
10331
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010332 skipCurrentReceiverLocked(app);
10333
10334 // Unregister any receivers.
10335 if (app.receivers.size() > 0) {
10336 Iterator<ReceiverList> it = app.receivers.iterator();
10337 while (it.hasNext()) {
10338 removeReceiverLocked(it.next());
10339 }
10340 app.receivers.clear();
10341 }
10342
Christopher Tate181fafa2009-05-14 11:12:14 -070010343 // If the app is undergoing backup, tell the backup manager about it
10344 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010345 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -070010346 try {
10347 IBackupManager bm = IBackupManager.Stub.asInterface(
10348 ServiceManager.getService(Context.BACKUP_SERVICE));
10349 bm.agentDisconnected(app.info.packageName);
10350 } catch (RemoteException e) {
10351 // can't happen; backup manager is local
10352 }
10353 }
10354
Jeff Sharkey287bd832011-05-28 19:36:26 -070010355 mHandler.obtainMessage(DISPATCH_PROCESS_DIED, app.pid, app.info.uid, null).sendToTarget();
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070010356
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010357 // If the caller is restarting this app, then leave it in its
10358 // current lists and let the caller take care of it.
10359 if (restarting) {
10360 return;
10361 }
10362
10363 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010364 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010365 "Removing non-persistent process during cleanup: " + app);
10366 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -070010367 if (mHeavyWeightProcess == app) {
10368 mHeavyWeightProcess = null;
10369 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
10370 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010371 } else if (!app.removed) {
10372 // This app is persistent, so we need to keep its record around.
10373 // If it is not already on the pending app list, add it there
10374 // and start a new process for it.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010375 if (mPersistentStartingProcesses.indexOf(app) < 0) {
10376 mPersistentStartingProcesses.add(app);
10377 restart = true;
10378 }
10379 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010380 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
10381 "Clean-up removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010382 mProcessesOnHold.remove(app);
10383
The Android Open Source Project4df24232009-03-05 14:34:35 -080010384 if (app == mHomeProcess) {
10385 mHomeProcess = null;
10386 }
Dianne Hackbornf35fe232011-11-01 19:25:20 -070010387 if (app == mPreviousProcess) {
10388 mPreviousProcess = null;
10389 }
10390
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010391 if (restart) {
10392 // We have components that still need to be running in the
10393 // process, so re-launch it.
10394 mProcessNames.put(app.processName, app.info.uid, app);
10395 startProcessLocked(app, "restart", app.processName);
10396 } else if (app.pid > 0 && app.pid != MY_PID) {
10397 // Goodbye!
10398 synchronized (mPidsSelfLocked) {
10399 mPidsSelfLocked.remove(app.pid);
10400 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
10401 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010402 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010403 }
10404 }
10405
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010406 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
10407 // Look through the content providers we are waiting to have launched,
10408 // and if any run in this process then either schedule a restart of
10409 // the process or kill the client waiting for it if this process has
10410 // gone bad.
10411 int NL = mLaunchingProviders.size();
10412 boolean restart = false;
10413 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010414 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010415 if (cpr.launchingApp == app) {
10416 if (!alwaysBad && !app.bad) {
10417 restart = true;
10418 } else {
10419 removeDyingProviderLocked(app, cpr);
10420 NL = mLaunchingProviders.size();
10421 }
10422 }
10423 }
10424 return restart;
10425 }
10426
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010427 // =========================================================
10428 // SERVICES
10429 // =========================================================
10430
10431 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
10432 ActivityManager.RunningServiceInfo info =
10433 new ActivityManager.RunningServiceInfo();
10434 info.service = r.name;
10435 if (r.app != null) {
10436 info.pid = r.app.pid;
10437 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010438 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010439 info.process = r.processName;
10440 info.foreground = r.isForeground;
10441 info.activeSince = r.createTime;
10442 info.started = r.startRequested;
10443 info.clientCount = r.connections.size();
10444 info.crashCount = r.crashCount;
10445 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010446 if (r.isForeground) {
10447 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
10448 }
10449 if (r.startRequested) {
10450 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
10451 }
Dan Egnor42471dd2010-01-07 17:25:22 -080010452 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010453 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
10454 }
10455 if (r.app != null && r.app.persistent) {
10456 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
10457 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010458
10459 for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
10460 for (int i=0; i<connl.size(); i++) {
10461 ConnectionRecord conn = connl.get(i);
10462 if (conn.clientLabel != 0) {
10463 info.clientPackage = conn.binding.client.info.packageName;
10464 info.clientLabel = conn.clientLabel;
10465 return info;
10466 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010467 }
10468 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010469 return info;
10470 }
10471
10472 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
10473 int flags) {
10474 synchronized (this) {
10475 ArrayList<ActivityManager.RunningServiceInfo> res
10476 = new ArrayList<ActivityManager.RunningServiceInfo>();
10477
10478 if (mServices.size() > 0) {
10479 Iterator<ServiceRecord> it = mServices.values().iterator();
10480 while (it.hasNext() && res.size() < maxNum) {
10481 res.add(makeRunningServiceInfoLocked(it.next()));
10482 }
10483 }
10484
10485 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
10486 ServiceRecord r = mRestartingServices.get(i);
10487 ActivityManager.RunningServiceInfo info =
10488 makeRunningServiceInfoLocked(r);
10489 info.restarting = r.nextRestartTime;
10490 res.add(info);
10491 }
10492
10493 return res;
10494 }
10495 }
10496
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010497 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
10498 synchronized (this) {
10499 ServiceRecord r = mServices.get(name);
10500 if (r != null) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010501 for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
10502 for (int i=0; i<conn.size(); i++) {
10503 if (conn.get(i).clientIntent != null) {
10504 return conn.get(i).clientIntent;
10505 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010506 }
10507 }
10508 }
10509 }
10510 return null;
10511 }
10512
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010513 private final ServiceRecord findServiceLocked(ComponentName name,
10514 IBinder token) {
10515 ServiceRecord r = mServices.get(name);
10516 return r == token ? r : null;
10517 }
10518
10519 private final class ServiceLookupResult {
10520 final ServiceRecord record;
10521 final String permission;
10522
10523 ServiceLookupResult(ServiceRecord _record, String _permission) {
10524 record = _record;
10525 permission = _permission;
10526 }
10527 };
10528
10529 private ServiceLookupResult findServiceLocked(Intent service,
10530 String resolvedType) {
10531 ServiceRecord r = null;
10532 if (service.getComponent() != null) {
10533 r = mServices.get(service.getComponent());
10534 }
10535 if (r == null) {
10536 Intent.FilterComparison filter = new Intent.FilterComparison(service);
10537 r = mServicesByIntent.get(filter);
10538 }
10539
10540 if (r == null) {
10541 try {
10542 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010543 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010544 service, resolvedType, 0);
10545 ServiceInfo sInfo =
10546 rInfo != null ? rInfo.serviceInfo : null;
10547 if (sInfo == null) {
10548 return null;
10549 }
10550
10551 ComponentName name = new ComponentName(
10552 sInfo.applicationInfo.packageName, sInfo.name);
10553 r = mServices.get(name);
10554 } catch (RemoteException ex) {
10555 // pm is in same process, this will never happen.
10556 }
10557 }
10558 if (r != null) {
10559 int callingPid = Binder.getCallingPid();
10560 int callingUid = Binder.getCallingUid();
10561 if (checkComponentPermission(r.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080010562 callingPid, callingUid, r.appInfo.uid, r.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010563 != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080010564 if (!r.exported) {
10565 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
10566 + " from pid=" + callingPid
10567 + ", uid=" + callingUid
10568 + " that is not exported from uid " + r.appInfo.uid);
10569 return new ServiceLookupResult(null, "not exported from uid "
10570 + r.appInfo.uid);
10571 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080010572 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010573 + " from pid=" + callingPid
10574 + ", uid=" + callingUid
10575 + " requires " + r.permission);
10576 return new ServiceLookupResult(null, r.permission);
10577 }
10578 return new ServiceLookupResult(r, null);
10579 }
10580 return null;
10581 }
10582
10583 private class ServiceRestarter implements Runnable {
10584 private ServiceRecord mService;
10585
10586 void setService(ServiceRecord service) {
10587 mService = service;
10588 }
10589
10590 public void run() {
10591 synchronized(ActivityManagerService.this) {
10592 performServiceRestartLocked(mService);
10593 }
10594 }
10595 }
10596
10597 private ServiceLookupResult retrieveServiceLocked(Intent service,
10598 String resolvedType, int callingPid, int callingUid) {
10599 ServiceRecord r = null;
10600 if (service.getComponent() != null) {
10601 r = mServices.get(service.getComponent());
10602 }
10603 Intent.FilterComparison filter = new Intent.FilterComparison(service);
10604 r = mServicesByIntent.get(filter);
10605 if (r == null) {
10606 try {
10607 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010608 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010609 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010610 ServiceInfo sInfo =
10611 rInfo != null ? rInfo.serviceInfo : null;
10612 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010613 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010614 ": not found");
10615 return null;
10616 }
10617
10618 ComponentName name = new ComponentName(
10619 sInfo.applicationInfo.packageName, sInfo.name);
10620 r = mServices.get(name);
10621 if (r == null) {
10622 filter = new Intent.FilterComparison(service.cloneFilter());
10623 ServiceRestarter res = new ServiceRestarter();
10624 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
10625 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
10626 synchronized (stats) {
10627 ss = stats.getServiceStatsLocked(
10628 sInfo.applicationInfo.uid, sInfo.packageName,
10629 sInfo.name);
10630 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -080010631 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010632 res.setService(r);
10633 mServices.put(name, r);
10634 mServicesByIntent.put(filter, r);
10635
10636 // Make sure this component isn't in the pending list.
10637 int N = mPendingServices.size();
10638 for (int i=0; i<N; i++) {
10639 ServiceRecord pr = mPendingServices.get(i);
10640 if (pr.name.equals(name)) {
10641 mPendingServices.remove(i);
10642 i--;
10643 N--;
10644 }
10645 }
10646 }
10647 } catch (RemoteException ex) {
10648 // pm is in same process, this will never happen.
10649 }
10650 }
10651 if (r != null) {
10652 if (checkComponentPermission(r.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080010653 callingPid, callingUid, r.appInfo.uid, r.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010654 != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080010655 if (!r.exported) {
10656 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
10657 + " from pid=" + callingPid
10658 + ", uid=" + callingUid
10659 + " that is not exported from uid " + r.appInfo.uid);
10660 return new ServiceLookupResult(null, "not exported from uid "
10661 + r.appInfo.uid);
10662 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080010663 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080010664 + " from pid=" + callingPid
10665 + ", uid=" + callingUid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010666 + " requires " + r.permission);
10667 return new ServiceLookupResult(null, r.permission);
10668 }
10669 return new ServiceLookupResult(r, null);
10670 }
10671 return null;
10672 }
10673
Dianne Hackborn287952c2010-09-22 22:34:31 -070010674 private final void bumpServiceExecutingLocked(ServiceRecord r, String why) {
10675 if (DEBUG_SERVICE) Log.v(TAG, ">>> EXECUTING "
10676 + why + " of " + r + " in app " + r.app);
10677 else if (DEBUG_SERVICE_EXECUTING) Log.v(TAG, ">>> EXECUTING "
10678 + why + " of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010679 long now = SystemClock.uptimeMillis();
10680 if (r.executeNesting == 0 && r.app != null) {
10681 if (r.app.executingServices.size() == 0) {
10682 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
10683 msg.obj = r.app;
10684 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
10685 }
10686 r.app.executingServices.add(r);
10687 }
10688 r.executeNesting++;
10689 r.executingStart = now;
10690 }
10691
10692 private final void sendServiceArgsLocked(ServiceRecord r,
10693 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010694 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010695 if (N == 0) {
10696 return;
10697 }
10698
Dianne Hackborn39792d22010-08-19 18:01:52 -070010699 while (r.pendingStarts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010700 try {
Dianne Hackborn39792d22010-08-19 18:01:52 -070010701 ServiceRecord.StartItem si = r.pendingStarts.remove(0);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010702 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
10703 + r + " " + r.intent + " args=" + si.intent);
Dianne Hackborn3a28f222011-03-01 12:25:54 -080010704 if (si.intent == null && N > 1) {
10705 // If somehow we got a dummy null intent in the middle,
10706 // then skip it. DO NOT skip a null intent when it is
10707 // the only one in the list -- this is to support the
10708 // onStartCommand(null) case.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010709 continue;
10710 }
Dianne Hackborn39792d22010-08-19 18:01:52 -070010711 si.deliveredTime = SystemClock.uptimeMillis();
10712 r.deliveredStarts.add(si);
10713 si.deliveryCount++;
Dianne Hackborn3a28f222011-03-01 12:25:54 -080010714 if (si.targetPermissionUid >= 0 && si.intent != null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -070010715 grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
Dianne Hackborn7e269642010-08-25 19:50:20 -070010716 r.packageName, si.intent, si.getUriPermissionsLocked());
Dianne Hackborn39792d22010-08-19 18:01:52 -070010717 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070010718 bumpServiceExecutingLocked(r, "start");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010719 if (!oomAdjusted) {
10720 oomAdjusted = true;
10721 updateOomAdjLocked(r.app);
10722 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010723 int flags = 0;
10724 if (si.deliveryCount > 0) {
10725 flags |= Service.START_FLAG_RETRY;
10726 }
10727 if (si.doneExecutingCount > 0) {
10728 flags |= Service.START_FLAG_REDELIVERY;
10729 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010730 r.app.thread.scheduleServiceArgs(r, si.taskRemoved, si.id, flags, si.intent);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010731 } catch (RemoteException e) {
10732 // Remote process gone... we'll let the normal cleanup take
10733 // care of this.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010734 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010735 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010736 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010737 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010738 break;
10739 }
10740 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010741 }
10742
10743 private final boolean requestServiceBindingLocked(ServiceRecord r,
10744 IntentBindRecord i, boolean rebind) {
10745 if (r.app == null || r.app.thread == null) {
10746 // If service is not currently running, can't yet bind.
10747 return false;
10748 }
10749 if ((!i.requested || rebind) && i.apps.size() > 0) {
10750 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010751 bumpServiceExecutingLocked(r, "bind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010752 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
10753 if (!rebind) {
10754 i.requested = true;
10755 }
10756 i.hasBound = true;
10757 i.doRebind = false;
10758 } catch (RemoteException e) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010759 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010760 return false;
10761 }
10762 }
10763 return true;
10764 }
10765
10766 private final void requestServiceBindingsLocked(ServiceRecord r) {
10767 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
10768 while (bindings.hasNext()) {
10769 IntentBindRecord i = bindings.next();
10770 if (!requestServiceBindingLocked(r, i, false)) {
10771 break;
10772 }
10773 }
10774 }
10775
10776 private final void realStartServiceLocked(ServiceRecord r,
10777 ProcessRecord app) throws RemoteException {
10778 if (app.thread == null) {
10779 throw new RemoteException();
10780 }
10781
10782 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -070010783 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010784
10785 app.services.add(r);
Dianne Hackborn287952c2010-09-22 22:34:31 -070010786 bumpServiceExecutingLocked(r, "create");
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010787 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010788
10789 boolean created = false;
10790 try {
Dianne Hackborna33e3f72009-09-29 17:28:24 -070010791 mStringBuilder.setLength(0);
Dianne Hackborn90c52de2011-09-23 12:57:44 -070010792 r.intent.getIntent().toShortString(mStringBuilder, true, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010793 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010794 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -070010795 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010796 synchronized (r.stats.getBatteryStats()) {
10797 r.stats.startLaunchedLocked();
10798 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070010799 ensurePackageDexOpt(r.serviceInfo.packageName);
Dianne Hackborne2515ee2011-04-27 18:52:56 -040010800 app.thread.scheduleCreateService(r, r.serviceInfo,
10801 compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo));
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010802 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010803 created = true;
10804 } finally {
10805 if (!created) {
10806 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010807 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010808 }
10809 }
10810
10811 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010812
10813 // If the service is in the started state, and there are no
10814 // pending arguments, then fake up one so its onStartCommand() will
10815 // be called.
10816 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010817 r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
10818 null, -1));
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010819 }
10820
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010821 sendServiceArgsLocked(r, true);
10822 }
10823
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010824 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
10825 boolean allowCancel) {
10826 boolean canceled = false;
10827
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010828 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010829 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -070010830 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010831
Dianne Hackborn070783f2010-12-29 16:46:28 -080010832 if ((r.serviceInfo.applicationInfo.flags
10833 &ApplicationInfo.FLAG_PERSISTENT) != 0) {
10834 minDuration /= 4;
10835 }
10836
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010837 // Any delivered but not yet finished starts should be put back
10838 // on the pending list.
10839 final int N = r.deliveredStarts.size();
10840 if (N > 0) {
10841 for (int i=N-1; i>=0; i--) {
10842 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
Dianne Hackborn39792d22010-08-19 18:01:52 -070010843 si.removeUriPermissionsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010844 if (si.intent == null) {
10845 // We'll generate this again if needed.
10846 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
10847 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
10848 r.pendingStarts.add(0, si);
10849 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
10850 dur *= 2;
10851 if (minDuration < dur) minDuration = dur;
10852 if (resetTime < dur) resetTime = dur;
10853 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010854 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010855 + r.name);
10856 canceled = true;
10857 }
10858 }
10859 r.deliveredStarts.clear();
10860 }
10861
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010862 r.totalRestartCount++;
10863 if (r.restartDelay == 0) {
10864 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010865 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010866 } else {
10867 // If it has been a "reasonably long time" since the service
10868 // was started, then reset our restart duration back to
10869 // the beginning, so we don't infinitely increase the duration
10870 // on a service that just occasionally gets killed (which is
10871 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010872 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010873 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010874 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010875 } else {
Dianne Hackborn070783f2010-12-29 16:46:28 -080010876 if ((r.serviceInfo.applicationInfo.flags
10877 &ApplicationInfo.FLAG_PERSISTENT) != 0) {
10878 // Services in peristent processes will restart much more
10879 // quickly, since they are pretty important. (Think SystemUI).
10880 r.restartDelay += minDuration/2;
10881 } else {
10882 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
10883 if (r.restartDelay < minDuration) {
10884 r.restartDelay = minDuration;
10885 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010886 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010887 }
10888 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010889
10890 r.nextRestartTime = now + r.restartDelay;
10891
10892 // Make sure that we don't end up restarting a bunch of services
10893 // all at the same time.
10894 boolean repeat;
10895 do {
10896 repeat = false;
10897 for (int i=mRestartingServices.size()-1; i>=0; i--) {
10898 ServiceRecord r2 = mRestartingServices.get(i);
10899 if (r2 != r && r.nextRestartTime
10900 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
10901 && r.nextRestartTime
10902 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
10903 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
10904 r.restartDelay = r.nextRestartTime - now;
10905 repeat = true;
10906 break;
10907 }
10908 }
10909 } while (repeat);
10910
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010911 if (!mRestartingServices.contains(r)) {
10912 mRestartingServices.add(r);
10913 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010914
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010915 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010916
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010917 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010918 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010919 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010920 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010921 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -080010922 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010923 r.shortName, r.restartDelay);
10924
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010925 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010926 }
10927
10928 final void performServiceRestartLocked(ServiceRecord r) {
10929 if (!mRestartingServices.contains(r)) {
10930 return;
10931 }
10932 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
10933 }
10934
10935 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
10936 if (r.restartDelay == 0) {
10937 return false;
10938 }
10939 r.resetRestartCounter();
10940 mRestartingServices.remove(r);
10941 mHandler.removeCallbacks(r.restarter);
10942 return true;
10943 }
10944
10945 private final boolean bringUpServiceLocked(ServiceRecord r,
10946 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010947 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010948 //r.dump(" ");
10949
Dianne Hackborn36124872009-10-08 16:22:03 -070010950 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010951 sendServiceArgsLocked(r, false);
10952 return true;
10953 }
10954
10955 if (!whileRestarting && r.restartDelay > 0) {
10956 // If waiting for a restart, then do nothing.
10957 return true;
10958 }
10959
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010960 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010961
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010962 // We are now bringing the service up, so no longer in the
10963 // restarting state.
10964 mRestartingServices.remove(r);
10965
Dianne Hackborne7f97212011-02-24 14:40:20 -080010966 // Service is now being launched, its package can't be stopped.
10967 try {
10968 AppGlobals.getPackageManager().setPackageStoppedState(
10969 r.packageName, false);
10970 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -080010971 } catch (IllegalArgumentException e) {
10972 Slog.w(TAG, "Failed trying to unstop package "
10973 + r.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -080010974 }
10975
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010976 final String appName = r.processName;
10977 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
10978 if (app != null && app.thread != null) {
10979 try {
Dianne Hackborn6c418d52011-06-29 14:05:33 -070010980 app.addPackage(r.appInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010981 realStartServiceLocked(r, app);
10982 return true;
10983 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010984 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010985 }
10986
10987 // If a dead object exception was thrown -- fall through to
10988 // restart the application.
10989 }
10990
Dianne Hackborn36124872009-10-08 16:22:03 -070010991 // Not running -- get it started, and enqueue this service record
10992 // to be executed when the app comes up.
10993 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
10994 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010995 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -070010996 + r.appInfo.packageName + "/"
10997 + r.appInfo.uid + " for service "
10998 + r.intent.getIntent() + ": process is bad");
10999 bringDownServiceLocked(r, true);
11000 return false;
11001 }
11002
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011003 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011004 mPendingServices.add(r);
11005 }
Dianne Hackborn36124872009-10-08 16:22:03 -070011006
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011007 return true;
11008 }
11009
11010 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011011 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011012 //r.dump(" ");
11013
11014 // Does it still need to run?
11015 if (!force && r.startRequested) {
11016 return;
11017 }
11018 if (r.connections.size() > 0) {
11019 if (!force) {
11020 // XXX should probably keep a count of the number of auto-create
11021 // connections directly in the service.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011022 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011023 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011024 ArrayList<ConnectionRecord> cr = it.next();
11025 for (int i=0; i<cr.size(); i++) {
11026 if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
11027 return;
11028 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011029 }
11030 }
11031 }
11032
11033 // Report to all of the connections that the service is no longer
11034 // available.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011035 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011036 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011037 ArrayList<ConnectionRecord> c = it.next();
11038 for (int i=0; i<c.size(); i++) {
Dianne Hackborn130b0d22011-07-26 22:07:48 -070011039 ConnectionRecord cr = c.get(i);
11040 // There is still a connection to the service that is
11041 // being brought down. Mark it as dead.
11042 cr.serviceDead = true;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011043 try {
Dianne Hackborn130b0d22011-07-26 22:07:48 -070011044 cr.conn.connected(r.name, null);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011045 } catch (Exception e) {
11046 Slog.w(TAG, "Failure disconnecting service " + r.name +
11047 " to connection " + c.get(i).conn.asBinder() +
11048 " (in " + c.get(i).binding.client.processName + ")", e);
11049 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011050 }
11051 }
11052 }
11053
11054 // Tell the service that it has been unbound.
11055 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
11056 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
11057 while (it.hasNext()) {
11058 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011059 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011060 + ": hasBound=" + ibr.hasBound);
11061 if (r.app != null && r.app.thread != null && ibr.hasBound) {
11062 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -070011063 bumpServiceExecutingLocked(r, "bring down unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011064 updateOomAdjLocked(r.app);
11065 ibr.hasBound = false;
11066 r.app.thread.scheduleUnbindService(r,
11067 ibr.intent.getIntent());
11068 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011069 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011070 + r.shortName, e);
11071 serviceDoneExecutingLocked(r, true);
11072 }
11073 }
11074 }
11075 }
11076
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011077 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011078 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011079 System.identityHashCode(r), r.shortName,
11080 (r.app != null) ? r.app.pid : -1);
11081
11082 mServices.remove(r.name);
11083 mServicesByIntent.remove(r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011084 r.totalRestartCount = 0;
11085 unscheduleServiceRestartLocked(r);
11086
11087 // Also make sure it is not on the pending list.
11088 int N = mPendingServices.size();
11089 for (int i=0; i<N; i++) {
11090 if (mPendingServices.get(i) == r) {
11091 mPendingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011092 if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011093 i--;
11094 N--;
11095 }
11096 }
11097
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011098 r.cancelNotification();
11099 r.isForeground = false;
11100 r.foregroundId = 0;
11101 r.foregroundNoti = null;
11102
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011103 // Clear start entries.
Dianne Hackborn39792d22010-08-19 18:01:52 -070011104 r.clearDeliveredStartsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011105 r.pendingStarts.clear();
11106
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011107 if (r.app != null) {
11108 synchronized (r.stats.getBatteryStats()) {
11109 r.stats.stopLaunchedLocked();
11110 }
11111 r.app.services.remove(r);
11112 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011113 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -070011114 bumpServiceExecutingLocked(r, "stop");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011115 mStoppingServices.add(r);
11116 updateOomAdjLocked(r.app);
11117 r.app.thread.scheduleStopService(r);
11118 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011119 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011120 + r.shortName, e);
11121 serviceDoneExecutingLocked(r, true);
11122 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011123 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011124 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011125 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011126 TAG, "Removed service that has no process: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011127 }
11128 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011129 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011130 TAG, "Removed service that is not running: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011131 }
Vairavan Srinivasana207ce22010-12-23 13:51:48 -080011132
11133 if (r.bindings.size() > 0) {
11134 r.bindings.clear();
11135 }
11136
11137 if (r.restarter instanceof ServiceRestarter) {
11138 ((ServiceRestarter)r.restarter).setService(null);
11139 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011140 }
11141
11142 ComponentName startServiceLocked(IApplicationThread caller,
11143 Intent service, String resolvedType,
11144 int callingPid, int callingUid) {
11145 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011146 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011147 + " type=" + resolvedType + " args=" + service.getExtras());
11148
11149 if (caller != null) {
11150 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11151 if (callerApp == null) {
11152 throw new SecurityException(
11153 "Unable to find app for caller " + caller
11154 + " (pid=" + Binder.getCallingPid()
11155 + ") when starting service " + service);
11156 }
11157 }
11158
11159 ServiceLookupResult res =
11160 retrieveServiceLocked(service, resolvedType,
11161 callingPid, callingUid);
11162 if (res == null) {
11163 return null;
11164 }
11165 if (res.record == null) {
11166 return new ComponentName("!", res.permission != null
11167 ? res.permission : "private to package");
11168 }
11169 ServiceRecord r = res.record;
Dianne Hackborn39792d22010-08-19 18:01:52 -070011170 int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
11171 callingUid, r.packageName, service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011172 if (unscheduleServiceRestartLocked(r)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011173 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011174 }
11175 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011176 r.callStart = false;
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070011177 r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
Dianne Hackborn39792d22010-08-19 18:01:52 -070011178 service, targetPermissionUid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011179 r.lastActivity = SystemClock.uptimeMillis();
11180 synchronized (r.stats.getBatteryStats()) {
11181 r.stats.startRunningLocked();
11182 }
11183 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
11184 return new ComponentName("!", "Service process is bad");
11185 }
11186 return r.name;
11187 }
11188 }
11189
11190 public ComponentName startService(IApplicationThread caller, Intent service,
11191 String resolvedType) {
11192 // Refuse possible leaked file descriptors
11193 if (service != null && service.hasFileDescriptors() == true) {
11194 throw new IllegalArgumentException("File descriptors passed in Intent");
11195 }
11196
11197 synchronized(this) {
11198 final int callingPid = Binder.getCallingPid();
11199 final int callingUid = Binder.getCallingUid();
11200 final long origId = Binder.clearCallingIdentity();
11201 ComponentName res = startServiceLocked(caller, service,
11202 resolvedType, callingPid, callingUid);
11203 Binder.restoreCallingIdentity(origId);
11204 return res;
11205 }
11206 }
11207
11208 ComponentName startServiceInPackage(int uid,
11209 Intent service, String resolvedType) {
11210 synchronized(this) {
11211 final long origId = Binder.clearCallingIdentity();
11212 ComponentName res = startServiceLocked(null, service,
11213 resolvedType, -1, uid);
11214 Binder.restoreCallingIdentity(origId);
11215 return res;
11216 }
11217 }
11218
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070011219 private void stopServiceLocked(ServiceRecord service) {
11220 synchronized (service.stats.getBatteryStats()) {
11221 service.stats.stopRunningLocked();
11222 }
11223 service.startRequested = false;
11224 service.callStart = false;
11225 bringDownServiceLocked(service, false);
11226 }
11227
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011228 public int stopService(IApplicationThread caller, Intent service,
11229 String resolvedType) {
11230 // Refuse possible leaked file descriptors
11231 if (service != null && service.hasFileDescriptors() == true) {
11232 throw new IllegalArgumentException("File descriptors passed in Intent");
11233 }
11234
11235 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011236 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011237 + " type=" + resolvedType);
11238
11239 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11240 if (caller != null && callerApp == null) {
11241 throw new SecurityException(
11242 "Unable to find app for caller " + caller
11243 + " (pid=" + Binder.getCallingPid()
11244 + ") when stopping service " + service);
11245 }
11246
11247 // If this service is active, make sure it is stopped.
11248 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11249 if (r != null) {
11250 if (r.record != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011251 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070011252 try {
11253 stopServiceLocked(r.record);
11254 } finally {
11255 Binder.restoreCallingIdentity(origId);
11256 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011257 return 1;
11258 }
11259 return -1;
11260 }
11261 }
11262
11263 return 0;
11264 }
11265
11266 public IBinder peekService(Intent service, String resolvedType) {
11267 // Refuse possible leaked file descriptors
11268 if (service != null && service.hasFileDescriptors() == true) {
11269 throw new IllegalArgumentException("File descriptors passed in Intent");
11270 }
11271
11272 IBinder ret = null;
11273
11274 synchronized(this) {
11275 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11276
11277 if (r != null) {
11278 // r.record is null if findServiceLocked() failed the caller permission check
11279 if (r.record == null) {
11280 throw new SecurityException(
11281 "Permission Denial: Accessing service " + r.record.name
11282 + " from pid=" + Binder.getCallingPid()
11283 + ", uid=" + Binder.getCallingUid()
11284 + " requires " + r.permission);
11285 }
11286 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
11287 if (ib != null) {
11288 ret = ib.binder;
11289 }
11290 }
11291 }
11292
11293 return ret;
11294 }
11295
11296 public boolean stopServiceToken(ComponentName className, IBinder token,
11297 int startId) {
11298 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011299 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011300 + " " + token + " startId=" + startId);
11301 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011302 if (r != null) {
11303 if (startId >= 0) {
11304 // Asked to only stop if done with all work. Note that
11305 // to avoid leaks, we will take this as dropping all
11306 // start items up to and including this one.
11307 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
11308 if (si != null) {
11309 while (r.deliveredStarts.size() > 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -070011310 ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
11311 cur.removeUriPermissionsLocked();
11312 if (cur == si) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011313 break;
11314 }
11315 }
11316 }
11317
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070011318 if (r.getLastStartId() != startId) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011319 return false;
11320 }
11321
11322 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011323 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011324 + " is last, but have " + r.deliveredStarts.size()
11325 + " remaining args");
11326 }
11327 }
11328
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011329 synchronized (r.stats.getBatteryStats()) {
11330 r.stats.stopRunningLocked();
11331 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011332 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011333 }
11334 final long origId = Binder.clearCallingIdentity();
11335 bringDownServiceLocked(r, false);
11336 Binder.restoreCallingIdentity(origId);
11337 return true;
11338 }
11339 }
11340 return false;
11341 }
11342
11343 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011344 int id, Notification notification, boolean removeNotification) {
11345 final long origId = Binder.clearCallingIdentity();
11346 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011347 synchronized(this) {
11348 ServiceRecord r = findServiceLocked(className, token);
11349 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011350 if (id != 0) {
11351 if (notification == null) {
11352 throw new IllegalArgumentException("null notification");
11353 }
11354 if (r.foregroundId != id) {
11355 r.cancelNotification();
11356 r.foregroundId = id;
11357 }
11358 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
11359 r.foregroundNoti = notification;
11360 r.isForeground = true;
11361 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011362 if (r.app != null) {
11363 updateServiceForegroundLocked(r.app, true);
11364 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011365 } else {
11366 if (r.isForeground) {
11367 r.isForeground = false;
11368 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -070011369 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011370 updateServiceForegroundLocked(r.app, true);
11371 }
11372 }
11373 if (removeNotification) {
11374 r.cancelNotification();
11375 r.foregroundId = 0;
11376 r.foregroundNoti = null;
11377 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011378 }
11379 }
11380 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011381 } finally {
11382 Binder.restoreCallingIdentity(origId);
11383 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011384 }
11385
11386 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
11387 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -070011388 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011389 if (sr.isForeground) {
11390 anyForeground = true;
11391 break;
11392 }
11393 }
11394 if (anyForeground != proc.foregroundServices) {
11395 proc.foregroundServices = anyForeground;
11396 if (oomAdj) {
11397 updateOomAdjLocked();
11398 }
11399 }
11400 }
11401
11402 public int bindService(IApplicationThread caller, IBinder token,
11403 Intent service, String resolvedType,
11404 IServiceConnection connection, int flags) {
11405 // Refuse possible leaked file descriptors
11406 if (service != null && service.hasFileDescriptors() == true) {
11407 throw new IllegalArgumentException("File descriptors passed in Intent");
11408 }
11409
11410 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011411 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011412 + " type=" + resolvedType + " conn=" + connection.asBinder()
11413 + " flags=0x" + Integer.toHexString(flags));
11414 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11415 if (callerApp == null) {
11416 throw new SecurityException(
11417 "Unable to find app for caller " + caller
11418 + " (pid=" + Binder.getCallingPid()
11419 + ") when binding service " + service);
11420 }
11421
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011422 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011423 if (token != null) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -070011424 activity = mMainStack.isInStackLocked(token);
11425 if (activity == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011426 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011427 return 0;
11428 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011429 }
11430
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011431 int clientLabel = 0;
11432 PendingIntent clientIntent = null;
11433
11434 if (callerApp.info.uid == Process.SYSTEM_UID) {
11435 // Hacky kind of thing -- allow system stuff to tell us
11436 // what they are, so we can report this elsewhere for
11437 // others to know why certain services are running.
11438 try {
11439 clientIntent = (PendingIntent)service.getParcelableExtra(
11440 Intent.EXTRA_CLIENT_INTENT);
11441 } catch (RuntimeException e) {
11442 }
11443 if (clientIntent != null) {
11444 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
11445 if (clientLabel != 0) {
11446 // There are no useful extras in the intent, trash them.
11447 // System code calling with this stuff just needs to know
11448 // this will happen.
11449 service = service.cloneFilter();
11450 }
11451 }
11452 }
11453
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011454 ServiceLookupResult res =
11455 retrieveServiceLocked(service, resolvedType,
11456 Binder.getCallingPid(), Binder.getCallingUid());
11457 if (res == null) {
11458 return 0;
11459 }
11460 if (res.record == null) {
11461 return -1;
11462 }
11463 ServiceRecord s = res.record;
11464
11465 final long origId = Binder.clearCallingIdentity();
11466
11467 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011468 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011469 + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011470 }
11471
11472 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
11473 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011474 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011475
11476 IBinder binder = connection.asBinder();
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011477 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
11478 if (clist == null) {
11479 clist = new ArrayList<ConnectionRecord>();
11480 s.connections.put(binder, clist);
11481 }
11482 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011483 b.connections.add(c);
11484 if (activity != null) {
11485 if (activity.connections == null) {
11486 activity.connections = new HashSet<ConnectionRecord>();
11487 }
11488 activity.connections.add(c);
11489 }
11490 b.client.connections.add(c);
Dianne Hackbornc68c9132011-07-29 01:25:18 -070011491 if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) {
11492 b.client.hasAboveClient = true;
11493 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011494 clist = mServiceConnections.get(binder);
11495 if (clist == null) {
11496 clist = new ArrayList<ConnectionRecord>();
11497 mServiceConnections.put(binder, clist);
11498 }
11499 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011500
11501 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
11502 s.lastActivity = SystemClock.uptimeMillis();
11503 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
11504 return 0;
11505 }
11506 }
11507
11508 if (s.app != null) {
11509 // This could have made the service more important.
11510 updateOomAdjLocked(s.app);
11511 }
11512
Joe Onorato8a9b2202010-02-26 18:56:32 -080011513 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011514 + ": received=" + b.intent.received
11515 + " apps=" + b.intent.apps.size()
11516 + " doRebind=" + b.intent.doRebind);
11517
11518 if (s.app != null && b.intent.received) {
11519 // Service is already running, so we can immediately
11520 // publish the connection.
11521 try {
11522 c.conn.connected(s.name, b.intent.binder);
11523 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011524 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011525 + " to connection " + c.conn.asBinder()
11526 + " (in " + c.binding.client.processName + ")", e);
11527 }
11528
11529 // If this is the first app connected back to this binding,
11530 // and the service had previously asked to be told when
11531 // rebound, then do so.
11532 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
11533 requestServiceBindingLocked(s, b.intent, true);
11534 }
11535 } else if (!b.intent.requested) {
11536 requestServiceBindingLocked(s, b.intent, false);
11537 }
11538
11539 Binder.restoreCallingIdentity(origId);
11540 }
11541
11542 return 1;
11543 }
11544
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011545 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011546 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011547 IBinder binder = c.conn.asBinder();
11548 AppBindRecord b = c.binding;
11549 ServiceRecord s = b.service;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011550 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
11551 if (clist != null) {
11552 clist.remove(c);
11553 if (clist.size() == 0) {
11554 s.connections.remove(binder);
11555 }
11556 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011557 b.connections.remove(c);
11558 if (c.activity != null && c.activity != skipAct) {
11559 if (c.activity.connections != null) {
11560 c.activity.connections.remove(c);
11561 }
11562 }
11563 if (b.client != skipApp) {
11564 b.client.connections.remove(c);
Dianne Hackbornc68c9132011-07-29 01:25:18 -070011565 if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) {
11566 b.client.updateHasAboveClientLocked();
11567 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011568 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011569 clist = mServiceConnections.get(binder);
11570 if (clist != null) {
11571 clist.remove(c);
11572 if (clist.size() == 0) {
11573 mServiceConnections.remove(binder);
11574 }
11575 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011576
11577 if (b.connections.size() == 0) {
11578 b.intent.apps.remove(b.client);
11579 }
11580
Dianne Hackborn130b0d22011-07-26 22:07:48 -070011581 if (!c.serviceDead) {
11582 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
11583 + ": shouldUnbind=" + b.intent.hasBound);
11584 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
11585 && b.intent.hasBound) {
11586 try {
11587 bumpServiceExecutingLocked(s, "unbind");
11588 updateOomAdjLocked(s.app);
11589 b.intent.hasBound = false;
11590 // Assume the client doesn't want to know about a rebind;
11591 // we will deal with that later if it asks for one.
11592 b.intent.doRebind = false;
11593 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
11594 } catch (Exception e) {
11595 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
11596 serviceDoneExecutingLocked(s, true);
11597 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011598 }
Dianne Hackborn130b0d22011-07-26 22:07:48 -070011599
11600 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
11601 bringDownServiceLocked(s, false);
11602 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011603 }
11604 }
11605
11606 public boolean unbindService(IServiceConnection connection) {
11607 synchronized (this) {
11608 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011609 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011610 ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
11611 if (clist == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011612 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011613 + connection.asBinder());
11614 return false;
11615 }
11616
11617 final long origId = Binder.clearCallingIdentity();
11618
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011619 while (clist.size() > 0) {
11620 ConnectionRecord r = clist.get(0);
11621 removeConnectionLocked(r, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011622
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011623 if (r.binding.service.app != null) {
11624 // This could have made the service less important.
11625 updateOomAdjLocked(r.binding.service.app);
11626 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011627 }
11628
11629 Binder.restoreCallingIdentity(origId);
11630 }
11631
11632 return true;
11633 }
11634
11635 public void publishService(IBinder token, Intent intent, IBinder service) {
11636 // Refuse possible leaked file descriptors
11637 if (intent != null && intent.hasFileDescriptors() == true) {
11638 throw new IllegalArgumentException("File descriptors passed in Intent");
11639 }
11640
11641 synchronized(this) {
11642 if (!(token instanceof ServiceRecord)) {
11643 throw new IllegalArgumentException("Invalid service token");
11644 }
11645 ServiceRecord r = (ServiceRecord)token;
11646
11647 final long origId = Binder.clearCallingIdentity();
11648
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011649 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011650 + " " + intent + ": " + service);
11651 if (r != null) {
11652 Intent.FilterComparison filter
11653 = new Intent.FilterComparison(intent);
11654 IntentBindRecord b = r.bindings.get(filter);
11655 if (b != null && !b.received) {
11656 b.binder = service;
11657 b.requested = true;
11658 b.received = true;
11659 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011660 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011661 = r.connections.values().iterator();
11662 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011663 ArrayList<ConnectionRecord> clist = it.next();
11664 for (int i=0; i<clist.size(); i++) {
11665 ConnectionRecord c = clist.get(i);
11666 if (!filter.equals(c.binding.intent.intent)) {
11667 if (DEBUG_SERVICE) Slog.v(
11668 TAG, "Not publishing to: " + c);
11669 if (DEBUG_SERVICE) Slog.v(
11670 TAG, "Bound intent: " + c.binding.intent.intent);
11671 if (DEBUG_SERVICE) Slog.v(
11672 TAG, "Published intent: " + intent);
11673 continue;
11674 }
11675 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
11676 try {
11677 c.conn.connected(r.name, service);
11678 } catch (Exception e) {
11679 Slog.w(TAG, "Failure sending service " + r.name +
11680 " to connection " + c.conn.asBinder() +
11681 " (in " + c.binding.client.processName + ")", e);
11682 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011683 }
11684 }
11685 }
11686 }
11687
11688 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
11689
11690 Binder.restoreCallingIdentity(origId);
11691 }
11692 }
11693 }
11694
11695 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
11696 // Refuse possible leaked file descriptors
11697 if (intent != null && intent.hasFileDescriptors() == true) {
11698 throw new IllegalArgumentException("File descriptors passed in Intent");
11699 }
11700
11701 synchronized(this) {
11702 if (!(token instanceof ServiceRecord)) {
11703 throw new IllegalArgumentException("Invalid service token");
11704 }
11705 ServiceRecord r = (ServiceRecord)token;
11706
11707 final long origId = Binder.clearCallingIdentity();
11708
11709 if (r != null) {
11710 Intent.FilterComparison filter
11711 = new Intent.FilterComparison(intent);
11712 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011713 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011714 + " at " + b + ": apps="
11715 + (b != null ? b.apps.size() : 0));
Per Edelberg78f9fff2010-08-30 20:01:35 +020011716
11717 boolean inStopping = mStoppingServices.contains(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011718 if (b != null) {
Per Edelberg78f9fff2010-08-30 20:01:35 +020011719 if (b.apps.size() > 0 && !inStopping) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011720 // Applications have already bound since the last
11721 // unbind, so just rebind right here.
11722 requestServiceBindingLocked(r, b, true);
11723 } else {
11724 // Note to tell the service the next time there is
11725 // a new client.
11726 b.doRebind = true;
11727 }
11728 }
11729
Per Edelberg78f9fff2010-08-30 20:01:35 +020011730 serviceDoneExecutingLocked(r, inStopping);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011731
11732 Binder.restoreCallingIdentity(origId);
11733 }
11734 }
11735 }
11736
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011737 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011738 synchronized(this) {
11739 if (!(token instanceof ServiceRecord)) {
11740 throw new IllegalArgumentException("Invalid service token");
11741 }
11742 ServiceRecord r = (ServiceRecord)token;
11743 boolean inStopping = mStoppingServices.contains(token);
11744 if (r != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011745 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011746 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011747 + " with incorrect token: given " + token
11748 + ", expected " + r);
11749 return;
11750 }
11751
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011752 if (type == 1) {
11753 // This is a call from a service start... take care of
11754 // book-keeping.
11755 r.callStart = true;
11756 switch (res) {
11757 case Service.START_STICKY_COMPATIBILITY:
11758 case Service.START_STICKY: {
11759 // We are done with the associated start arguments.
11760 r.findDeliveredStart(startId, true);
11761 // Don't stop if killed.
11762 r.stopIfKilled = false;
11763 break;
11764 }
11765 case Service.START_NOT_STICKY: {
11766 // We are done with the associated start arguments.
11767 r.findDeliveredStart(startId, true);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070011768 if (r.getLastStartId() == startId) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011769 // There is no more work, and this service
11770 // doesn't want to hang around if killed.
11771 r.stopIfKilled = true;
11772 }
11773 break;
11774 }
11775 case Service.START_REDELIVER_INTENT: {
11776 // We'll keep this item until they explicitly
11777 // call stop for it, but keep track of the fact
11778 // that it was delivered.
11779 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
11780 if (si != null) {
11781 si.deliveryCount = 0;
11782 si.doneExecutingCount++;
11783 // Don't stop if killed.
11784 r.stopIfKilled = true;
11785 }
11786 break;
11787 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070011788 case Service.START_TASK_REMOVED_COMPLETE: {
11789 // Special processing for onTaskRemoved(). Don't
11790 // impact normal onStartCommand() processing.
11791 r.findDeliveredStart(startId, true);
11792 break;
11793 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011794 default:
11795 throw new IllegalArgumentException(
11796 "Unknown service start result: " + res);
11797 }
11798 if (res == Service.START_STICKY_COMPATIBILITY) {
11799 r.callStart = false;
11800 }
11801 }
11802
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011803 final long origId = Binder.clearCallingIdentity();
11804 serviceDoneExecutingLocked(r, inStopping);
11805 Binder.restoreCallingIdentity(origId);
11806 } else {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011807 Slog.w(TAG, "Done executing unknown service from pid "
11808 + Binder.getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011809 }
11810 }
11811 }
11812
11813 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011814 if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
11815 + ": nesting=" + r.executeNesting
11816 + ", inStopping=" + inStopping + ", app=" + r.app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070011817 else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011818 r.executeNesting--;
11819 if (r.executeNesting <= 0 && r.app != null) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070011820 if (DEBUG_SERVICE) Slog.v(TAG,
11821 "Nesting at 0 of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011822 r.app.executingServices.remove(r);
11823 if (r.app.executingServices.size() == 0) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070011824 if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,
11825 "No more executingServices of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011826 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
11827 }
11828 if (inStopping) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070011829 if (DEBUG_SERVICE) Slog.v(TAG,
11830 "doneExecuting remove stopping " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011831 mStoppingServices.remove(r);
Mattias Petersson3996b412010-10-27 09:32:51 +020011832 r.bindings.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011833 }
11834 updateOomAdjLocked(r.app);
11835 }
11836 }
11837
11838 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011839 String anrMessage = null;
11840
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011841 synchronized(this) {
11842 if (proc.executingServices.size() == 0 || proc.thread == null) {
11843 return;
11844 }
11845 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
11846 Iterator<ServiceRecord> it = proc.executingServices.iterator();
11847 ServiceRecord timeout = null;
11848 long nextTime = 0;
11849 while (it.hasNext()) {
11850 ServiceRecord sr = it.next();
11851 if (sr.executingStart < maxTime) {
11852 timeout = sr;
11853 break;
11854 }
11855 if (sr.executingStart > nextTime) {
11856 nextTime = sr.executingStart;
11857 }
11858 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011859 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011860 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011861 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011862 } else {
11863 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
11864 msg.obj = proc;
11865 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
11866 }
11867 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011868
11869 if (anrMessage != null) {
11870 appNotResponding(proc, null, null, anrMessage);
11871 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011872 }
11873
11874 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070011875 // BACKUP AND RESTORE
11876 // =========================================================
11877
11878 // Cause the target app to be launched if necessary and its backup agent
11879 // instantiated. The backup agent will invoke backupAgentCreated() on the
11880 // activity manager to announce its creation.
11881 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011882 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070011883 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
11884
11885 synchronized(this) {
11886 // !!! TODO: currently no check here that we're already bound
11887 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
11888 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
11889 synchronized (stats) {
11890 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
11891 }
11892
Dianne Hackborne7f97212011-02-24 14:40:20 -080011893 // Backup agent is now in use, its package can't be stopped.
11894 try {
11895 AppGlobals.getPackageManager().setPackageStoppedState(
11896 app.packageName, false);
11897 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -080011898 } catch (IllegalArgumentException e) {
11899 Slog.w(TAG, "Failed trying to unstop package "
11900 + app.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -080011901 }
11902
Christopher Tate181fafa2009-05-14 11:12:14 -070011903 BackupRecord r = new BackupRecord(ss, app, backupMode);
Christopher Tate4a627c72011-04-01 14:43:32 -070011904 ComponentName hostingName = (backupMode == IApplicationThread.BACKUP_MODE_INCREMENTAL)
11905 ? new ComponentName(app.packageName, app.backupAgentName)
11906 : new ComponentName("android", "FullBackupAgent");
Christopher Tate181fafa2009-05-14 11:12:14 -070011907 // startProcessLocked() returns existing proc's record if it's already running
11908 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011909 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070011910 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011911 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070011912 return false;
11913 }
11914
11915 r.app = proc;
11916 mBackupTarget = r;
11917 mBackupAppName = app.packageName;
11918
Christopher Tate6fa95972009-06-05 18:43:55 -070011919 // Try not to kill the process during backup
11920 updateOomAdjLocked(proc);
11921
Christopher Tate181fafa2009-05-14 11:12:14 -070011922 // If the process is already attached, schedule the creation of the backup agent now.
11923 // If it is not yet live, this will be done when it attaches to the framework.
11924 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011925 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070011926 try {
Dianne Hackborne2515ee2011-04-27 18:52:56 -040011927 proc.thread.scheduleCreateBackupAgent(app,
11928 compatibilityInfoForPackageLocked(app), backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070011929 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070011930 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070011931 }
11932 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011933 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070011934 }
11935 // Invariants: at this point, the target app process exists and the application
11936 // is either already running or in the process of coming up. mBackupTarget and
11937 // mBackupAppName describe the app, so that when it binds back to the AM we
11938 // know that it's scheduled for a backup-agent operation.
11939 }
11940
11941 return true;
11942 }
11943
11944 // A backup agent has just come up
11945 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011946 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070011947 + " = " + agent);
11948
11949 synchronized(this) {
11950 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011951 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070011952 return;
11953 }
Dianne Hackborn06740692010-09-22 22:46:21 -070011954 }
Christopher Tate181fafa2009-05-14 11:12:14 -070011955
Dianne Hackborn06740692010-09-22 22:46:21 -070011956 long oldIdent = Binder.clearCallingIdentity();
11957 try {
11958 IBackupManager bm = IBackupManager.Stub.asInterface(
11959 ServiceManager.getService(Context.BACKUP_SERVICE));
11960 bm.agentConnected(agentPackageName, agent);
11961 } catch (RemoteException e) {
11962 // can't happen; the backup manager service is local
11963 } catch (Exception e) {
11964 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
11965 e.printStackTrace();
11966 } finally {
11967 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070011968 }
11969 }
11970
11971 // done with this agent
11972 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011973 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070011974 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011975 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070011976 return;
11977 }
Christopher Tate181fafa2009-05-14 11:12:14 -070011978
11979 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070011980 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011981 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070011982 return;
11983 }
11984
Christopher Tate181fafa2009-05-14 11:12:14 -070011985 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011986 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070011987 return;
11988 }
11989
Christopher Tate6fa95972009-06-05 18:43:55 -070011990 ProcessRecord proc = mBackupTarget.app;
11991 mBackupTarget = null;
11992 mBackupAppName = null;
11993
11994 // Not backing this app up any more; reset its OOM adjustment
11995 updateOomAdjLocked(proc);
11996
Christopher Tatec7b31e32009-06-10 15:49:30 -070011997 // If the app crashed during backup, 'thread' will be null here
11998 if (proc.thread != null) {
11999 try {
Dianne Hackborne2515ee2011-04-27 18:52:56 -040012000 proc.thread.scheduleDestroyBackupAgent(appInfo,
12001 compatibilityInfoForPackageLocked(appInfo));
Christopher Tatec7b31e32009-06-10 15:49:30 -070012002 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012003 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070012004 e.printStackTrace();
12005 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012006 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012007 }
12008 }
12009 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012010 // BROADCASTS
12011 // =========================================================
12012
Josh Bartel7f208742010-02-25 11:01:44 -060012013 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012014 List cur) {
12015 final ContentResolver resolver = mContext.getContentResolver();
12016 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
12017 if (list == null) {
12018 return cur;
12019 }
12020 int N = list.size();
12021 for (int i=0; i<N; i++) {
12022 Intent intent = list.get(i);
12023 if (filter.match(resolver, intent, true, TAG) >= 0) {
12024 if (cur == null) {
12025 cur = new ArrayList<Intent>();
12026 }
12027 cur.add(intent);
12028 }
12029 }
12030 return cur;
12031 }
12032
12033 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012034 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012035 + mBroadcastsScheduled);
12036
12037 if (mBroadcastsScheduled) {
12038 return;
12039 }
12040 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
12041 mBroadcastsScheduled = true;
12042 }
12043
Dianne Hackborn6c418d52011-06-29 14:05:33 -070012044 public Intent registerReceiver(IApplicationThread caller, String callerPackage,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012045 IIntentReceiver receiver, IntentFilter filter, String permission) {
12046 synchronized(this) {
12047 ProcessRecord callerApp = null;
12048 if (caller != null) {
12049 callerApp = getRecordForAppLocked(caller);
12050 if (callerApp == null) {
12051 throw new SecurityException(
12052 "Unable to find app for caller " + caller
12053 + " (pid=" + Binder.getCallingPid()
12054 + ") when registering receiver " + receiver);
12055 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -070012056 if (callerApp.info.uid != Process.SYSTEM_UID &&
12057 !callerApp.pkgList.contains(callerPackage)) {
12058 throw new SecurityException("Given caller package " + callerPackage
12059 + " is not running in process " + callerApp);
12060 }
12061 } else {
12062 callerPackage = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012063 }
12064
12065 List allSticky = null;
12066
12067 // Look for any matching sticky broadcasts...
12068 Iterator actions = filter.actionsIterator();
12069 if (actions != null) {
12070 while (actions.hasNext()) {
12071 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -060012072 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012073 }
12074 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060012075 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012076 }
12077
12078 // The first sticky in the list is returned directly back to
12079 // the client.
12080 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
12081
Joe Onorato8a9b2202010-02-26 18:56:32 -080012082 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012083 + ": " + sticky);
12084
12085 if (receiver == null) {
12086 return sticky;
12087 }
12088
12089 ReceiverList rl
12090 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
12091 if (rl == null) {
12092 rl = new ReceiverList(this, callerApp,
12093 Binder.getCallingPid(),
12094 Binder.getCallingUid(), receiver);
12095 if (rl.app != null) {
12096 rl.app.receivers.add(rl);
12097 } else {
12098 try {
12099 receiver.asBinder().linkToDeath(rl, 0);
12100 } catch (RemoteException e) {
12101 return sticky;
12102 }
12103 rl.linkedToDeath = true;
12104 }
12105 mRegisteredReceivers.put(receiver.asBinder(), rl);
12106 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -070012107 BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage, permission);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012108 rl.add(bf);
12109 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012110 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012111 }
12112 mReceiverResolver.addFilter(bf);
12113
12114 // Enqueue broadcasts for all existing stickies that match
12115 // this filter.
12116 if (allSticky != null) {
12117 ArrayList receivers = new ArrayList();
12118 receivers.add(bf);
12119
12120 int N = allSticky.size();
12121 for (int i=0; i<N; i++) {
12122 Intent intent = (Intent)allSticky.get(i);
12123 BroadcastRecord r = new BroadcastRecord(intent, null,
12124 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012125 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012126 if (mParallelBroadcasts.size() == 0) {
12127 scheduleBroadcastsLocked();
12128 }
12129 mParallelBroadcasts.add(r);
12130 }
12131 }
12132
12133 return sticky;
12134 }
12135 }
12136
12137 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012138 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012139
12140 boolean doNext = false;
12141
12142 synchronized(this) {
12143 ReceiverList rl
12144 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
12145 if (rl != null) {
12146 if (rl.curBroadcast != null) {
12147 BroadcastRecord r = rl.curBroadcast;
12148 doNext = finishReceiverLocked(
12149 receiver.asBinder(), r.resultCode, r.resultData,
12150 r.resultExtras, r.resultAbort, true);
12151 }
12152
12153 if (rl.app != null) {
12154 rl.app.receivers.remove(rl);
12155 }
12156 removeReceiverLocked(rl);
12157 if (rl.linkedToDeath) {
12158 rl.linkedToDeath = false;
12159 rl.receiver.asBinder().unlinkToDeath(rl, 0);
12160 }
12161 }
12162 }
12163
12164 if (!doNext) {
12165 return;
12166 }
12167
12168 final long origId = Binder.clearCallingIdentity();
12169 processNextBroadcast(false);
12170 trimApplications();
12171 Binder.restoreCallingIdentity(origId);
12172 }
12173
12174 void removeReceiverLocked(ReceiverList rl) {
12175 mRegisteredReceivers.remove(rl.receiver.asBinder());
12176 int N = rl.size();
12177 for (int i=0; i<N; i++) {
12178 mReceiverResolver.removeFilter(rl.get(i));
12179 }
12180 }
12181
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070012182 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
12183 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
12184 ProcessRecord r = mLruProcesses.get(i);
12185 if (r.thread != null) {
12186 try {
12187 r.thread.dispatchPackageBroadcast(cmd, packages);
12188 } catch (RemoteException ex) {
12189 }
12190 }
12191 }
12192 }
12193
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012194 private final int broadcastIntentLocked(ProcessRecord callerApp,
12195 String callerPackage, Intent intent, String resolvedType,
12196 IIntentReceiver resultTo, int resultCode, String resultData,
12197 Bundle map, String requiredPermission,
12198 boolean ordered, boolean sticky, int callingPid, int callingUid) {
12199 intent = new Intent(intent);
12200
Dianne Hackborne7f97212011-02-24 14:40:20 -080012201 // By default broadcasts do not go to stopped apps.
12202 intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
12203
Joe Onorato8a9b2202010-02-26 18:56:32 -080012204 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012205 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
12206 + " ordered=" + ordered);
12207 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012208 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012209 }
12210
12211 // Handle special intents: if this broadcast is from the package
12212 // manager about a package being removed, we need to remove all of
12213 // its activities from the history stack.
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070012214 final boolean uidRemoved = Intent.ACTION_UID_REMOVED.equals(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012215 intent.getAction());
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070012216 if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
12217 || Intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012218 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012219 || uidRemoved) {
12220 if (checkComponentPermission(
12221 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080012222 callingPid, callingUid, -1, true)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012223 == PackageManager.PERMISSION_GRANTED) {
12224 if (uidRemoved) {
12225 final Bundle intentExtras = intent.getExtras();
12226 final int uid = intentExtras != null
12227 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
12228 if (uid >= 0) {
12229 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
12230 synchronized (bs) {
12231 bs.removeUidStatsLocked(uid);
12232 }
12233 }
12234 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012235 // If resources are unvailble just force stop all
12236 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012237 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012238 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
12239 if (list != null && (list.length > 0)) {
12240 for (String pkg : list) {
Christopher Tate3dacd842011-08-19 14:56:15 -070012241 forceStopPackageLocked(pkg, -1, false, true, true, false);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012242 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070012243 sendPackageBroadcastLocked(
12244 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012245 }
12246 } else {
12247 Uri data = intent.getData();
12248 String ssp;
12249 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
12250 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
12251 forceStopPackageLocked(ssp,
Christopher Tate3dacd842011-08-19 14:56:15 -070012252 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true, false);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070012253 }
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070012254 if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070012255 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
12256 new String[] {ssp});
12257 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012258 }
12259 }
12260 }
12261 } else {
12262 String msg = "Permission Denial: " + intent.getAction()
12263 + " broadcast from " + callerPackage + " (pid=" + callingPid
12264 + ", uid=" + callingUid + ")"
12265 + " requires "
12266 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012267 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012268 throw new SecurityException(msg);
12269 }
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070012270
12271 // Special case for adding a package: by default turn on compatibility
12272 // mode.
12273 } else if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())) {
Dianne Hackborn8ea5e1d2011-05-27 16:45:31 -070012274 Uri data = intent.getData();
12275 String ssp;
12276 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
12277 mCompatModePackages.handlePackageAddedLocked(ssp,
12278 intent.getBooleanExtra(Intent.EXTRA_REPLACING, false));
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070012279 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012280 }
12281
12282 /*
12283 * If this is the time zone changed action, queue up a message that will reset the timezone
12284 * of all currently running processes. This message will get queued up before the broadcast
12285 * happens.
12286 */
12287 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
12288 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
12289 }
12290
Robert Greenwalt03595d02010-11-02 14:08:23 -070012291 if (intent.ACTION_CLEAR_DNS_CACHE.equals(intent.getAction())) {
12292 mHandler.sendEmptyMessage(CLEAR_DNS_CACHE);
12293 }
12294
Robert Greenwalt434203a2010-10-11 16:00:27 -070012295 if (Proxy.PROXY_CHANGE_ACTION.equals(intent.getAction())) {
12296 ProxyProperties proxy = intent.getParcelableExtra("proxy");
12297 mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY, proxy));
12298 }
12299
Dianne Hackborn854060af2009-07-09 18:14:31 -070012300 /*
12301 * Prevent non-system code (defined here to be non-persistent
12302 * processes) from sending protected broadcasts.
12303 */
12304 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
12305 || callingUid == Process.SHELL_UID || callingUid == 0) {
12306 // Always okay.
12307 } else if (callerApp == null || !callerApp.persistent) {
12308 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012309 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -070012310 intent.getAction())) {
12311 String msg = "Permission Denial: not allowed to send broadcast "
12312 + intent.getAction() + " from pid="
12313 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012314 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070012315 throw new SecurityException(msg);
12316 }
12317 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012318 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070012319 return BROADCAST_SUCCESS;
12320 }
12321 }
12322
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012323 // Add to the sticky list if requested.
12324 if (sticky) {
12325 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
12326 callingPid, callingUid)
12327 != PackageManager.PERMISSION_GRANTED) {
12328 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
12329 + callingPid + ", uid=" + callingUid
12330 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012331 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012332 throw new SecurityException(msg);
12333 }
12334 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012335 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012336 + " and enforce permission " + requiredPermission);
12337 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
12338 }
12339 if (intent.getComponent() != null) {
12340 throw new SecurityException(
12341 "Sticky broadcasts can't target a specific component");
12342 }
12343 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
12344 if (list == null) {
12345 list = new ArrayList<Intent>();
12346 mStickyBroadcasts.put(intent.getAction(), list);
12347 }
12348 int N = list.size();
12349 int i;
12350 for (i=0; i<N; i++) {
12351 if (intent.filterEquals(list.get(i))) {
12352 // This sticky already exists, replace it.
12353 list.set(i, new Intent(intent));
12354 break;
12355 }
12356 }
12357 if (i >= N) {
12358 list.add(new Intent(intent));
12359 }
12360 }
12361
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012362 // Figure out who all will receive this broadcast.
12363 List receivers = null;
12364 List<BroadcastFilter> registeredReceivers = null;
12365 try {
12366 if (intent.getComponent() != null) {
12367 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012368 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070012369 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012370 if (ai != null) {
12371 receivers = new ArrayList();
12372 ResolveInfo ri = new ResolveInfo();
12373 ri.activityInfo = ai;
12374 receivers.add(ri);
12375 }
12376 } else {
12377 // Need to resolve the intent to interested receivers...
12378 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
12379 == 0) {
12380 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012381 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012382 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012383 }
Mihai Preda074edef2009-05-18 17:13:31 +020012384 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012385 }
12386 } catch (RemoteException ex) {
12387 // pm is in same process, this will never happen.
12388 }
12389
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012390 final boolean replacePending =
12391 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
12392
Joe Onorato8a9b2202010-02-26 18:56:32 -080012393 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012394 + " replacePending=" + replacePending);
12395
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012396 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
12397 if (!ordered && NR > 0) {
12398 // If we are not serializing this broadcast, then send the
12399 // registered receivers separately so they don't wait for the
12400 // components to be launched.
12401 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12402 callerPackage, callingPid, callingUid, requiredPermission,
12403 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012404 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012405 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012406 TAG, "Enqueueing parallel broadcast " + r
12407 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012408 boolean replaced = false;
12409 if (replacePending) {
12410 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
12411 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012412 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012413 "***** DROPPING PARALLEL: " + intent);
12414 mParallelBroadcasts.set(i, r);
12415 replaced = true;
12416 break;
12417 }
12418 }
12419 }
12420 if (!replaced) {
12421 mParallelBroadcasts.add(r);
12422 scheduleBroadcastsLocked();
12423 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012424 registeredReceivers = null;
12425 NR = 0;
12426 }
12427
12428 // Merge into one list.
12429 int ir = 0;
12430 if (receivers != null) {
12431 // A special case for PACKAGE_ADDED: do not allow the package
12432 // being added to see this broadcast. This prevents them from
12433 // using this as a back door to get run as soon as they are
12434 // installed. Maybe in the future we want to have a special install
12435 // broadcast or such for apps, but we'd like to deliberately make
12436 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012437 String skipPackages[] = null;
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070012438 if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
12439 || Intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
12440 || Intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012441 Uri data = intent.getData();
12442 if (data != null) {
12443 String pkgName = data.getSchemeSpecificPart();
12444 if (pkgName != null) {
12445 skipPackages = new String[] { pkgName };
12446 }
12447 }
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070012448 } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012449 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070012450 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012451 if (skipPackages != null && (skipPackages.length > 0)) {
12452 for (String skipPackage : skipPackages) {
12453 if (skipPackage != null) {
12454 int NT = receivers.size();
12455 for (int it=0; it<NT; it++) {
12456 ResolveInfo curt = (ResolveInfo)receivers.get(it);
12457 if (curt.activityInfo.packageName.equals(skipPackage)) {
12458 receivers.remove(it);
12459 it--;
12460 NT--;
12461 }
12462 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012463 }
12464 }
12465 }
12466
12467 int NT = receivers != null ? receivers.size() : 0;
12468 int it = 0;
12469 ResolveInfo curt = null;
12470 BroadcastFilter curr = null;
12471 while (it < NT && ir < NR) {
12472 if (curt == null) {
12473 curt = (ResolveInfo)receivers.get(it);
12474 }
12475 if (curr == null) {
12476 curr = registeredReceivers.get(ir);
12477 }
12478 if (curr.getPriority() >= curt.priority) {
12479 // Insert this broadcast record into the final list.
12480 receivers.add(it, curr);
12481 ir++;
12482 curr = null;
12483 it++;
12484 NT++;
12485 } else {
12486 // Skip to the next ResolveInfo in the final list.
12487 it++;
12488 curt = null;
12489 }
12490 }
12491 }
12492 while (ir < NR) {
12493 if (receivers == null) {
12494 receivers = new ArrayList();
12495 }
12496 receivers.add(registeredReceivers.get(ir));
12497 ir++;
12498 }
12499
12500 if ((receivers != null && receivers.size() > 0)
12501 || resultTo != null) {
12502 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12503 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012504 receivers, resultTo, resultCode, resultData, map, ordered,
12505 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012506 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012507 TAG, "Enqueueing ordered broadcast " + r
12508 + ": prev had " + mOrderedBroadcasts.size());
12509 if (DEBUG_BROADCAST) {
12510 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012511 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012512 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012513 boolean replaced = false;
12514 if (replacePending) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012515 for (int i=mOrderedBroadcasts.size()-1; i>0; i--) {
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012516 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012517 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012518 "***** DROPPING ORDERED: " + intent);
12519 mOrderedBroadcasts.set(i, r);
12520 replaced = true;
12521 break;
12522 }
12523 }
12524 }
12525 if (!replaced) {
12526 mOrderedBroadcasts.add(r);
12527 scheduleBroadcastsLocked();
12528 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012529 }
12530
12531 return BROADCAST_SUCCESS;
12532 }
12533
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012534 final Intent verifyBroadcastLocked(Intent intent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012535 // Refuse possible leaked file descriptors
12536 if (intent != null && intent.hasFileDescriptors() == true) {
12537 throw new IllegalArgumentException("File descriptors passed in Intent");
12538 }
12539
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012540 int flags = intent.getFlags();
12541
12542 if (!mProcessesReady) {
12543 // if the caller really truly claims to know what they're doing, go
12544 // ahead and allow the broadcast without launching any receivers
12545 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
12546 intent = new Intent(intent);
12547 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
12548 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
12549 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
12550 + " before boot completion");
12551 throw new IllegalStateException("Cannot broadcast before boot completed");
12552 }
12553 }
12554
12555 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
12556 throw new IllegalArgumentException(
12557 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
12558 }
12559
12560 return intent;
12561 }
12562
12563 public final int broadcastIntent(IApplicationThread caller,
12564 Intent intent, String resolvedType, IIntentReceiver resultTo,
12565 int resultCode, String resultData, Bundle map,
12566 String requiredPermission, boolean serialized, boolean sticky) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012567 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012568 intent = verifyBroadcastLocked(intent);
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012569
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012570 final ProcessRecord callerApp = getRecordForAppLocked(caller);
12571 final int callingPid = Binder.getCallingPid();
12572 final int callingUid = Binder.getCallingUid();
12573 final long origId = Binder.clearCallingIdentity();
12574 int res = broadcastIntentLocked(callerApp,
12575 callerApp != null ? callerApp.info.packageName : null,
12576 intent, resolvedType, resultTo,
12577 resultCode, resultData, map, requiredPermission, serialized,
12578 sticky, callingPid, callingUid);
12579 Binder.restoreCallingIdentity(origId);
12580 return res;
12581 }
12582 }
12583
12584 int broadcastIntentInPackage(String packageName, int uid,
12585 Intent intent, String resolvedType, IIntentReceiver resultTo,
12586 int resultCode, String resultData, Bundle map,
12587 String requiredPermission, boolean serialized, boolean sticky) {
12588 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012589 intent = verifyBroadcastLocked(intent);
12590
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012591 final long origId = Binder.clearCallingIdentity();
12592 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
12593 resultTo, resultCode, resultData, map, requiredPermission,
12594 serialized, sticky, -1, uid);
12595 Binder.restoreCallingIdentity(origId);
12596 return res;
12597 }
12598 }
12599
12600 public final void unbroadcastIntent(IApplicationThread caller,
12601 Intent intent) {
12602 // Refuse possible leaked file descriptors
12603 if (intent != null && intent.hasFileDescriptors() == true) {
12604 throw new IllegalArgumentException("File descriptors passed in Intent");
12605 }
12606
12607 synchronized(this) {
12608 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
12609 != PackageManager.PERMISSION_GRANTED) {
12610 String msg = "Permission Denial: unbroadcastIntent() from pid="
12611 + Binder.getCallingPid()
12612 + ", uid=" + Binder.getCallingUid()
12613 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012614 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012615 throw new SecurityException(msg);
12616 }
12617 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
12618 if (list != null) {
12619 int N = list.size();
12620 int i;
12621 for (i=0; i<N; i++) {
12622 if (intent.filterEquals(list.get(i))) {
12623 list.remove(i);
12624 break;
12625 }
12626 }
12627 }
12628 }
12629 }
12630
12631 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
12632 String resultData, Bundle resultExtras, boolean resultAbort,
12633 boolean explicit) {
12634 if (mOrderedBroadcasts.size() == 0) {
12635 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012636 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012637 }
12638 return false;
12639 }
12640 BroadcastRecord r = mOrderedBroadcasts.get(0);
12641 if (r.receiver == null) {
12642 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012643 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012644 }
12645 return false;
12646 }
12647 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012648 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012649 return false;
12650 }
12651 int state = r.state;
Dianne Hackbornce86ba82011-07-13 19:33:41 -070012652 r.state = BroadcastRecord.IDLE;
12653 if (state == BroadcastRecord.IDLE) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012654 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012655 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012656 }
12657 }
12658 r.receiver = null;
12659 r.intent.setComponent(null);
12660 if (r.curApp != null) {
12661 r.curApp.curReceiver = null;
12662 }
12663 if (r.curFilter != null) {
12664 r.curFilter.receiverList.curBroadcast = null;
12665 }
12666 r.curFilter = null;
12667 r.curApp = null;
12668 r.curComponent = null;
12669 r.curReceiver = null;
12670 mPendingBroadcast = null;
12671
12672 r.resultCode = resultCode;
12673 r.resultData = resultData;
12674 r.resultExtras = resultExtras;
12675 r.resultAbort = resultAbort;
12676
12677 // We will process the next receiver right now if this is finishing
12678 // an app receiver (which is always asynchronous) or after we have
12679 // come back from calling a receiver.
12680 return state == BroadcastRecord.APP_RECEIVE
12681 || state == BroadcastRecord.CALL_DONE_RECEIVE;
12682 }
12683
12684 public void finishReceiver(IBinder who, int resultCode, String resultData,
12685 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012686 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012687
12688 // Refuse possible leaked file descriptors
12689 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
12690 throw new IllegalArgumentException("File descriptors passed in Bundle");
12691 }
12692
12693 boolean doNext;
12694
12695 final long origId = Binder.clearCallingIdentity();
12696
12697 synchronized(this) {
12698 doNext = finishReceiverLocked(
12699 who, resultCode, resultData, resultExtras, resultAbort, true);
12700 }
12701
12702 if (doNext) {
12703 processNextBroadcast(false);
12704 }
12705 trimApplications();
12706
12707 Binder.restoreCallingIdentity(origId);
12708 }
12709
Jeff Brown4d94a762010-09-23 11:33:28 -070012710 private final void logBroadcastReceiverDiscardLocked(BroadcastRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012711 if (r.nextReceiver > 0) {
12712 Object curReceiver = r.receivers.get(r.nextReceiver-1);
12713 if (curReceiver instanceof BroadcastFilter) {
12714 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080012715 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012716 System.identityHashCode(r),
12717 r.intent.getAction(),
12718 r.nextReceiver - 1,
12719 System.identityHashCode(bf));
12720 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080012721 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012722 System.identityHashCode(r),
12723 r.intent.getAction(),
12724 r.nextReceiver - 1,
12725 ((ResolveInfo)curReceiver).toString());
12726 }
12727 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012728 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012729 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080012730 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012731 System.identityHashCode(r),
12732 r.intent.getAction(),
12733 r.nextReceiver,
12734 "NONE");
12735 }
12736 }
12737
Jeff Brown4d94a762010-09-23 11:33:28 -070012738 private final void setBroadcastTimeoutLocked(long timeoutTime) {
12739 if (! mPendingBroadcastTimeoutMessage) {
12740 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
12741 mHandler.sendMessageAtTime(msg, timeoutTime);
12742 mPendingBroadcastTimeoutMessage = true;
12743 }
12744 }
12745
12746 private final void cancelBroadcastTimeoutLocked() {
12747 if (mPendingBroadcastTimeoutMessage) {
12748 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
12749 mPendingBroadcastTimeoutMessage = false;
12750 }
12751 }
12752
12753 private final void broadcastTimeoutLocked(boolean fromMsg) {
12754 if (fromMsg) {
12755 mPendingBroadcastTimeoutMessage = false;
12756 }
12757
12758 if (mOrderedBroadcasts.size() == 0) {
12759 return;
12760 }
12761
12762 long now = SystemClock.uptimeMillis();
12763 BroadcastRecord r = mOrderedBroadcasts.get(0);
12764 if (fromMsg) {
12765 if (mDidDexOpt) {
12766 // Delay timeouts until dexopt finishes.
12767 mDidDexOpt = false;
12768 long timeoutTime = SystemClock.uptimeMillis() + BROADCAST_TIMEOUT;
12769 setBroadcastTimeoutLocked(timeoutTime);
12770 return;
12771 }
12772 if (! mProcessesReady) {
12773 // Only process broadcast timeouts if the system is ready. That way
12774 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
12775 // to do heavy lifting for system up.
12776 return;
12777 }
12778
12779 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
12780 if (timeoutTime > now) {
12781 // We can observe premature timeouts because we do not cancel and reset the
12782 // broadcast timeout message after each receiver finishes. Instead, we set up
12783 // an initial timeout then kick it down the road a little further as needed
12784 // when it expires.
12785 if (DEBUG_BROADCAST) Slog.v(TAG,
12786 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
12787 + timeoutTime);
12788 setBroadcastTimeoutLocked(timeoutTime);
12789 return;
12790 }
12791 }
12792
12793 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver
12794 + ", started " + (now - r.receiverTime) + "ms ago");
12795 r.receiverTime = now;
12796 r.anrCount++;
12797
12798 // Current receiver has passed its expiration date.
12799 if (r.nextReceiver <= 0) {
12800 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
12801 return;
12802 }
12803
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012804 ProcessRecord app = null;
12805 String anrMessage = null;
12806
Jeff Brown4d94a762010-09-23 11:33:28 -070012807 Object curReceiver = r.receivers.get(r.nextReceiver-1);
12808 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
12809 logBroadcastReceiverDiscardLocked(r);
12810 if (curReceiver instanceof BroadcastFilter) {
12811 BroadcastFilter bf = (BroadcastFilter)curReceiver;
12812 if (bf.receiverList.pid != 0
12813 && bf.receiverList.pid != MY_PID) {
12814 synchronized (this.mPidsSelfLocked) {
12815 app = this.mPidsSelfLocked.get(
12816 bf.receiverList.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012817 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012818 }
Jeff Brown4d94a762010-09-23 11:33:28 -070012819 } else {
12820 app = r.curApp;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012821 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012822
Jeff Brown4d94a762010-09-23 11:33:28 -070012823 if (app != null) {
12824 anrMessage = "Broadcast of " + r.intent.toString();
12825 }
12826
12827 if (mPendingBroadcast == r) {
12828 mPendingBroadcast = null;
12829 }
12830
12831 // Move on to the next receiver.
12832 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
12833 r.resultExtras, r.resultAbort, true);
12834 scheduleBroadcastsLocked();
12835
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012836 if (anrMessage != null) {
Jeff Brown4d94a762010-09-23 11:33:28 -070012837 // Post the ANR to the handler since we do not want to process ANRs while
12838 // potentially holding our lock.
12839 mHandler.post(new AppNotResponding(app, anrMessage));
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012840 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012841 }
12842
12843 private final void processCurBroadcastLocked(BroadcastRecord r,
12844 ProcessRecord app) throws RemoteException {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012845 if (DEBUG_BROADCAST) Slog.v(TAG,
12846 "Process cur broadcast " + r + " for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012847 if (app.thread == null) {
12848 throw new RemoteException();
12849 }
12850 r.receiver = app.thread.asBinder();
12851 r.curApp = app;
12852 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012853 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012854
12855 // Tell the application to launch this receiver.
12856 r.intent.setComponent(r.curComponent);
12857
12858 boolean started = false;
12859 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012860 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012861 "Delivering to component " + r.curComponent
12862 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070012863 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012864 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
Dianne Hackborne2515ee2011-04-27 18:52:56 -040012865 compatibilityInfoForPackageLocked(r.curReceiver.applicationInfo),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012866 r.resultCode, r.resultData, r.resultExtras, r.ordered);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012867 if (DEBUG_BROADCAST) Slog.v(TAG,
12868 "Process cur broadcast " + r + " DELIVERED for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012869 started = true;
12870 } finally {
12871 if (!started) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012872 if (DEBUG_BROADCAST) Slog.v(TAG,
12873 "Process cur broadcast " + r + ": NOT STARTED!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012874 r.receiver = null;
12875 r.curApp = null;
12876 app.curReceiver = null;
12877 }
12878 }
12879
12880 }
12881
Jeff Brown4d94a762010-09-23 11:33:28 -070012882 static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012883 Intent intent, int resultCode, String data, Bundle extras,
12884 boolean ordered, boolean sticky) throws RemoteException {
Jeff Brown4d94a762010-09-23 11:33:28 -070012885 // Send the intent to the receiver asynchronously using one-way binder calls.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012886 if (app != null && app.thread != null) {
12887 // If we have an app thread, do the call through that so it is
12888 // correctly ordered with other one-way calls.
12889 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012890 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012891 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012892 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012893 }
12894 }
12895
Jeff Brown4d94a762010-09-23 11:33:28 -070012896 private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012897 BroadcastFilter filter, boolean ordered) {
12898 boolean skip = false;
12899 if (filter.requiredPermission != null) {
12900 int perm = checkComponentPermission(filter.requiredPermission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080012901 r.callingPid, r.callingUid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012902 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012903 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012904 + r.intent.toString()
12905 + " from " + r.callerPackage + " (pid="
12906 + r.callingPid + ", uid=" + r.callingUid + ")"
12907 + " requires " + filter.requiredPermission
12908 + " due to registered receiver " + filter);
12909 skip = true;
12910 }
12911 }
12912 if (r.requiredPermission != null) {
12913 int perm = checkComponentPermission(r.requiredPermission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080012914 filter.receiverList.pid, filter.receiverList.uid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012915 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012916 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012917 + r.intent.toString()
12918 + " to " + filter.receiverList.app
12919 + " (pid=" + filter.receiverList.pid
12920 + ", uid=" + filter.receiverList.uid + ")"
12921 + " requires " + r.requiredPermission
12922 + " due to sender " + r.callerPackage
12923 + " (uid " + r.callingUid + ")");
12924 skip = true;
12925 }
12926 }
12927
12928 if (!skip) {
12929 // If this is not being sent as an ordered broadcast, then we
12930 // don't want to touch the fields that keep track of the current
12931 // state of ordered broadcasts.
12932 if (ordered) {
12933 r.receiver = filter.receiverList.receiver.asBinder();
12934 r.curFilter = filter;
12935 filter.receiverList.curBroadcast = r;
12936 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012937 if (filter.receiverList.app != null) {
12938 // Bump hosting application to no longer be in background
12939 // scheduling class. Note that we can't do that if there
12940 // isn't an app... but we can only be in that case for
12941 // things that directly call the IActivityManager API, which
12942 // are already core system stuff so don't matter for this.
12943 r.curApp = filter.receiverList.app;
12944 filter.receiverList.app.curReceiver = r;
12945 updateOomAdjLocked();
12946 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012947 }
12948 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012949 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012950 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070012951 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012952 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012953 }
Jeff Brown4d94a762010-09-23 11:33:28 -070012954 performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012955 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012956 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012957 if (ordered) {
12958 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
12959 }
12960 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012961 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012962 if (ordered) {
12963 r.receiver = null;
12964 r.curFilter = null;
12965 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012966 if (filter.receiverList.app != null) {
12967 filter.receiverList.app.curReceiver = null;
12968 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012969 }
12970 }
12971 }
12972 }
12973
Dianne Hackborn12527f92009-11-11 17:39:50 -080012974 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
12975 if (r.callingUid < 0) {
12976 // This was from a registerReceiver() call; ignore it.
12977 return;
12978 }
12979 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
12980 MAX_BROADCAST_HISTORY-1);
12981 r.finishTime = SystemClock.uptimeMillis();
12982 mBroadcastHistory[0] = r;
12983 }
12984
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012985 private final void processNextBroadcast(boolean fromMsg) {
12986 synchronized(this) {
12987 BroadcastRecord r;
12988
Joe Onorato8a9b2202010-02-26 18:56:32 -080012989 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012990 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070012991 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012992
12993 updateCpuStats();
12994
12995 if (fromMsg) {
12996 mBroadcastsScheduled = false;
12997 }
12998
12999 // First, deliver any non-serialized broadcasts right away.
13000 while (mParallelBroadcasts.size() > 0) {
13001 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080013002 r.dispatchTime = SystemClock.uptimeMillis();
Dianne Hackbornd99b2932011-08-18 14:39:58 -070013003 r.dispatchClockTime = System.currentTimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013004 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080013005 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013006 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013007 for (int i=0; i<N; i++) {
13008 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013009 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013010 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013011 + target + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070013012 deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013013 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080013014 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013015 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013016 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013017 }
13018
13019 // Now take care of the next serialized one...
13020
13021 // If we are waiting for a process to come up to handle the next
13022 // broadcast, then do nothing at this point. Just in case, we
13023 // check that the process we're waiting for still exists.
13024 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070013025 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013026 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070013027 + mPendingBroadcast.curApp);
13028 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013029
13030 boolean isDead;
13031 synchronized (mPidsSelfLocked) {
13032 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
13033 }
13034 if (!isDead) {
13035 // It's still alive, so keep waiting
13036 return;
13037 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013038 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013039 + " died before responding to broadcast");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070013040 mPendingBroadcast.state = BroadcastRecord.IDLE;
13041 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013042 mPendingBroadcast = null;
13043 }
13044 }
13045
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013046 boolean looped = false;
13047
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013048 do {
13049 if (mOrderedBroadcasts.size() == 0) {
13050 // No more broadcasts pending, so all done!
13051 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013052 if (looped) {
13053 // If we had finished the last ordered broadcast, then
13054 // make sure all processes have correct oom and sched
13055 // adjustments.
13056 updateOomAdjLocked();
13057 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013058 return;
13059 }
13060 r = mOrderedBroadcasts.get(0);
13061 boolean forceReceive = false;
13062
13063 // Ensure that even if something goes awry with the timeout
13064 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050013065 // and continue to make progress.
13066 //
13067 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
Jeff Brown4d94a762010-09-23 11:33:28 -070013068 // receivers don't get executed with timeouts. They're intended for
Jeff Hamiltonacf84742010-05-25 22:10:18 -050013069 // one time heavy lifting after system upgrades and can take
13070 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013071 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070013072 if (mProcessesReady && r.dispatchTime > 0) {
Jeff Hamiltonacf84742010-05-25 22:10:18 -050013073 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013074 if ((numReceivers > 0) &&
13075 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013076 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013077 + " now=" + now
13078 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080013079 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013080 + " intent=" + r.intent
13081 + " numReceivers=" + numReceivers
13082 + " nextReceiver=" + r.nextReceiver
13083 + " state=" + r.state);
Jeff Brown4d94a762010-09-23 11:33:28 -070013084 broadcastTimeoutLocked(false); // forcibly finish this broadcast
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013085 forceReceive = true;
13086 r.state = BroadcastRecord.IDLE;
13087 }
13088 }
13089
13090 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013091 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013092 "processNextBroadcast() called when not idle (state="
13093 + r.state + ")");
13094 return;
13095 }
13096
13097 if (r.receivers == null || r.nextReceiver >= numReceivers
13098 || r.resultAbort || forceReceive) {
13099 // No more receivers for this broadcast! Send the final
13100 // result if requested...
13101 if (r.resultTo != null) {
13102 try {
13103 if (DEBUG_BROADCAST) {
13104 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013105 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013106 + " seq=" + seq + " app=" + r.callerApp);
13107 }
Jeff Brown4d94a762010-09-23 11:33:28 -070013108 performReceiveLocked(r.callerApp, r.resultTo,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013109 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070013110 r.resultData, r.resultExtras, false, false);
Johannes Carlssonb5a86542010-10-27 10:08:10 +020013111 // Set this to null so that the reference
13112 // (local and remote) isnt kept in the mBroadcastHistory.
13113 r.resultTo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013114 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013115 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013116 }
13117 }
13118
Joe Onorato8a9b2202010-02-26 18:56:32 -080013119 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
Jeff Brown4d94a762010-09-23 11:33:28 -070013120 cancelBroadcastTimeoutLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013121
Joe Onorato8a9b2202010-02-26 18:56:32 -080013122 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013123 + r);
13124
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013125 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080013126 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013127 mOrderedBroadcasts.remove(0);
13128 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013129 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013130 continue;
13131 }
13132 } while (r == null);
13133
13134 // Get the next receiver...
13135 int recIdx = r.nextReceiver++;
13136
13137 // Keep track of when this receiver started, and make sure there
13138 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080013139 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013140 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080013141 r.dispatchTime = r.receiverTime;
Dianne Hackbornd99b2932011-08-18 14:39:58 -070013142 r.dispatchClockTime = System.currentTimeMillis();
Joe Onorato8a9b2202010-02-26 18:56:32 -080013143 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013144 + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070013145 }
13146 if (! mPendingBroadcastTimeoutMessage) {
13147 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013148 if (DEBUG_BROADCAST) Slog.v(TAG,
Jeff Brown4d94a762010-09-23 11:33:28 -070013149 "Submitting BROADCAST_TIMEOUT_MSG for " + r + " at " + timeoutTime);
13150 setBroadcastTimeoutLocked(timeoutTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013151 }
13152
13153 Object nextReceiver = r.receivers.get(recIdx);
13154 if (nextReceiver instanceof BroadcastFilter) {
13155 // Simple case: this is a registered receiver who gets
13156 // a direct call.
13157 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013158 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013159 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013160 + filter + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070013161 deliverToRegisteredReceiverLocked(r, filter, r.ordered);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013162 if (r.receiver == null || !r.ordered) {
13163 // The receiver has already finished, so schedule to
13164 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013165 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
13166 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013167 r.state = BroadcastRecord.IDLE;
13168 scheduleBroadcastsLocked();
13169 }
13170 return;
13171 }
13172
13173 // Hard case: need to instantiate the receiver, possibly
13174 // starting its application process to host it.
13175
13176 ResolveInfo info =
13177 (ResolveInfo)nextReceiver;
13178
13179 boolean skip = false;
13180 int perm = checkComponentPermission(info.activityInfo.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080013181 r.callingPid, r.callingUid, info.activityInfo.applicationInfo.uid,
13182 info.activityInfo.exported);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013183 if (perm != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080013184 if (!info.activityInfo.exported) {
13185 Slog.w(TAG, "Permission Denial: broadcasting "
13186 + r.intent.toString()
13187 + " from " + r.callerPackage + " (pid=" + r.callingPid
13188 + ", uid=" + r.callingUid + ")"
13189 + " is not exported from uid " + info.activityInfo.applicationInfo.uid
13190 + " due to receiver " + info.activityInfo.packageName
13191 + "/" + info.activityInfo.name);
13192 } else {
13193 Slog.w(TAG, "Permission Denial: broadcasting "
13194 + r.intent.toString()
13195 + " from " + r.callerPackage + " (pid=" + r.callingPid
13196 + ", uid=" + r.callingUid + ")"
13197 + " requires " + info.activityInfo.permission
13198 + " due to receiver " + info.activityInfo.packageName
13199 + "/" + info.activityInfo.name);
13200 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013201 skip = true;
13202 }
Dianne Hackbornd99b2932011-08-18 14:39:58 -070013203 if (info.activityInfo.applicationInfo.uid != Process.SYSTEM_UID &&
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013204 r.requiredPermission != null) {
13205 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013206 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013207 checkPermission(r.requiredPermission,
13208 info.activityInfo.applicationInfo.packageName);
13209 } catch (RemoteException e) {
13210 perm = PackageManager.PERMISSION_DENIED;
13211 }
13212 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013213 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013214 + r.intent + " to "
13215 + info.activityInfo.applicationInfo.packageName
13216 + " requires " + r.requiredPermission
13217 + " due to sender " + r.callerPackage
13218 + " (uid " + r.callingUid + ")");
13219 skip = true;
13220 }
13221 }
13222 if (r.curApp != null && r.curApp.crashing) {
13223 // If the target process is crashing, just skip it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070013224 if (DEBUG_BROADCAST) Slog.v(TAG,
13225 "Skipping deliver ordered " + r + " to " + r.curApp
13226 + ": process crashing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013227 skip = true;
13228 }
13229
13230 if (skip) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070013231 if (DEBUG_BROADCAST) Slog.v(TAG,
13232 "Skipping delivery of ordered " + r + " for whatever reason");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013233 r.receiver = null;
13234 r.curFilter = null;
13235 r.state = BroadcastRecord.IDLE;
13236 scheduleBroadcastsLocked();
13237 return;
13238 }
13239
13240 r.state = BroadcastRecord.APP_RECEIVE;
13241 String targetProcess = info.activityInfo.processName;
13242 r.curComponent = new ComponentName(
13243 info.activityInfo.applicationInfo.packageName,
13244 info.activityInfo.name);
13245 r.curReceiver = info.activityInfo;
13246
Dianne Hackborne7f97212011-02-24 14:40:20 -080013247 // Broadcast is being executed, its package can't be stopped.
13248 try {
13249 AppGlobals.getPackageManager().setPackageStoppedState(
13250 r.curComponent.getPackageName(), false);
13251 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -080013252 } catch (IllegalArgumentException e) {
13253 Slog.w(TAG, "Failed trying to unstop package "
13254 + r.curComponent.getPackageName() + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -080013255 }
13256
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013257 // Is this receiver's application already running?
13258 ProcessRecord app = getProcessRecordLocked(targetProcess,
13259 info.activityInfo.applicationInfo.uid);
13260 if (app != null && app.thread != null) {
13261 try {
Dianne Hackborn6c418d52011-06-29 14:05:33 -070013262 app.addPackage(info.activityInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013263 processCurBroadcastLocked(r, app);
13264 return;
13265 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013266 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013267 + r.curComponent, e);
13268 }
13269
13270 // If a dead object exception was thrown -- fall through to
13271 // restart the application.
13272 }
13273
Dianne Hackborn9acc0302009-08-25 00:27:12 -070013274 // Not running -- get it started, to be executed when the app comes up.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070013275 if (DEBUG_BROADCAST) Slog.v(TAG,
13276 "Need to start app " + targetProcess + " for broadcast " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013277 if ((r.curApp=startProcessLocked(targetProcess,
13278 info.activityInfo.applicationInfo, true,
13279 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070013280 "broadcast", r.curComponent,
13281 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
13282 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013283 // Ah, this recipient is unavailable. Finish it if necessary,
13284 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013285 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013286 + info.activityInfo.applicationInfo.packageName + "/"
13287 + info.activityInfo.applicationInfo.uid + " for broadcast "
13288 + r.intent + ": process is bad");
Jeff Brown4d94a762010-09-23 11:33:28 -070013289 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013290 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
13291 r.resultExtras, r.resultAbort, true);
13292 scheduleBroadcastsLocked();
13293 r.state = BroadcastRecord.IDLE;
13294 return;
13295 }
13296
13297 mPendingBroadcast = r;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070013298 mPendingBroadcastRecvIndex = recIdx;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013299 }
13300 }
13301
13302 // =========================================================
13303 // INSTRUMENTATION
13304 // =========================================================
13305
13306 public boolean startInstrumentation(ComponentName className,
13307 String profileFile, int flags, Bundle arguments,
13308 IInstrumentationWatcher watcher) {
13309 // Refuse possible leaked file descriptors
13310 if (arguments != null && arguments.hasFileDescriptors()) {
13311 throw new IllegalArgumentException("File descriptors passed in Bundle");
13312 }
13313
13314 synchronized(this) {
13315 InstrumentationInfo ii = null;
13316 ApplicationInfo ai = null;
13317 try {
13318 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013319 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013320 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013321 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013322 } catch (PackageManager.NameNotFoundException e) {
13323 }
13324 if (ii == null) {
13325 reportStartInstrumentationFailure(watcher, className,
13326 "Unable to find instrumentation info for: " + className);
13327 return false;
13328 }
13329 if (ai == null) {
13330 reportStartInstrumentationFailure(watcher, className,
13331 "Unable to find instrumentation target package: " + ii.targetPackage);
13332 return false;
13333 }
13334
13335 int match = mContext.getPackageManager().checkSignatures(
13336 ii.targetPackage, ii.packageName);
13337 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
13338 String msg = "Permission Denial: starting instrumentation "
13339 + className + " from pid="
13340 + Binder.getCallingPid()
13341 + ", uid=" + Binder.getCallingPid()
13342 + " not allowed because package " + ii.packageName
13343 + " does not have a signature matching the target "
13344 + ii.targetPackage;
13345 reportStartInstrumentationFailure(watcher, className, msg);
13346 throw new SecurityException(msg);
13347 }
13348
13349 final long origId = Binder.clearCallingIdentity();
Christopher Tate3dacd842011-08-19 14:56:15 -070013350 // Instrumentation can kill and relaunch even persistent processes
13351 forceStopPackageLocked(ii.targetPackage, -1, true, false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013352 ProcessRecord app = addAppLocked(ai);
13353 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013354 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013355 app.instrumentationProfileFile = profileFile;
13356 app.instrumentationArguments = arguments;
13357 app.instrumentationWatcher = watcher;
13358 app.instrumentationResultClass = className;
13359 Binder.restoreCallingIdentity(origId);
13360 }
13361
13362 return true;
13363 }
13364
13365 /**
13366 * Report errors that occur while attempting to start Instrumentation. Always writes the
13367 * error to the logs, but if somebody is watching, send the report there too. This enables
13368 * the "am" command to report errors with more information.
13369 *
13370 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
13371 * @param cn The component name of the instrumentation.
13372 * @param report The error report.
13373 */
13374 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
13375 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013376 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013377 try {
13378 if (watcher != null) {
13379 Bundle results = new Bundle();
13380 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
13381 results.putString("Error", report);
13382 watcher.instrumentationStatus(cn, -1, results);
13383 }
13384 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013385 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013386 }
13387 }
13388
13389 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
13390 if (app.instrumentationWatcher != null) {
13391 try {
13392 // NOTE: IInstrumentationWatcher *must* be oneway here
13393 app.instrumentationWatcher.instrumentationFinished(
13394 app.instrumentationClass,
13395 resultCode,
13396 results);
13397 } catch (RemoteException e) {
13398 }
13399 }
13400 app.instrumentationWatcher = null;
13401 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013402 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013403 app.instrumentationProfileFile = null;
13404 app.instrumentationArguments = null;
13405
Christopher Tate3dacd842011-08-19 14:56:15 -070013406 forceStopPackageLocked(app.processName, -1, false, false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013407 }
13408
13409 public void finishInstrumentation(IApplicationThread target,
13410 int resultCode, Bundle results) {
13411 // Refuse possible leaked file descriptors
13412 if (results != null && results.hasFileDescriptors()) {
13413 throw new IllegalArgumentException("File descriptors passed in Intent");
13414 }
13415
13416 synchronized(this) {
13417 ProcessRecord app = getRecordForAppLocked(target);
13418 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013419 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013420 return;
13421 }
13422 final long origId = Binder.clearCallingIdentity();
13423 finishInstrumentationLocked(app, resultCode, results);
13424 Binder.restoreCallingIdentity(origId);
13425 }
13426 }
13427
13428 // =========================================================
13429 // CONFIGURATION
13430 // =========================================================
13431
13432 public ConfigurationInfo getDeviceConfigurationInfo() {
13433 ConfigurationInfo config = new ConfigurationInfo();
13434 synchronized (this) {
13435 config.reqTouchScreen = mConfiguration.touchscreen;
13436 config.reqKeyboardType = mConfiguration.keyboard;
13437 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013438 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
13439 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013440 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
13441 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013442 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
13443 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013444 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
13445 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070013446 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013447 }
13448 return config;
13449 }
13450
13451 public Configuration getConfiguration() {
13452 Configuration ci;
13453 synchronized(this) {
13454 ci = new Configuration(mConfiguration);
13455 }
13456 return ci;
13457 }
13458
Dianne Hackborn31ca8542011-07-19 14:58:28 -070013459 public void updatePersistentConfiguration(Configuration values) {
13460 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
13461 "updateConfiguration()");
13462 enforceCallingPermission(android.Manifest.permission.WRITE_SETTINGS,
13463 "updateConfiguration()");
13464 if (values == null) {
13465 throw new NullPointerException("Configuration must not be null");
13466 }
13467
13468 synchronized(this) {
13469 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn813075a62011-11-14 17:45:19 -080013470 updateConfigurationLocked(values, null, true, false);
Dianne Hackborn31ca8542011-07-19 14:58:28 -070013471 Binder.restoreCallingIdentity(origId);
13472 }
13473 }
13474
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013475 public void updateConfiguration(Configuration values) {
13476 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
13477 "updateConfiguration()");
13478
13479 synchronized(this) {
13480 if (values == null && mWindowManager != null) {
13481 // sentinel: fetch the current configuration from the window manager
13482 values = mWindowManager.computeNewConfiguration();
13483 }
Dianne Hackborn7d608422011-08-07 16:24:18 -070013484
13485 if (mWindowManager != null) {
13486 mProcessList.applyDisplaySize(mWindowManager);
13487 }
13488
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013489 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn31ca8542011-07-19 14:58:28 -070013490 if (values != null) {
13491 Settings.System.clearConfiguration(values);
13492 }
Dianne Hackborn813075a62011-11-14 17:45:19 -080013493 updateConfigurationLocked(values, null, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013494 Binder.restoreCallingIdentity(origId);
13495 }
13496 }
13497
13498 /**
13499 * Do either or both things: (1) change the current configuration, and (2)
13500 * make sure the given activity is running with the (now) current
13501 * configuration. Returns true if the activity has been left running, or
13502 * false if <var>starting</var> is being destroyed to match the new
13503 * configuration.
Dianne Hackborn31ca8542011-07-19 14:58:28 -070013504 * @param persistent TODO
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013505 */
13506 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn813075a62011-11-14 17:45:19 -080013507 ActivityRecord starting, boolean persistent, boolean initLocale) {
Mike Lockwooda0a8b242011-08-12 13:55:22 -070013508 // do nothing if we are headless
13509 if (mHeadless) return true;
13510
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013511 int changes = 0;
13512
13513 boolean kept = true;
13514
13515 if (values != null) {
13516 Configuration newConfig = new Configuration(mConfiguration);
13517 changes = newConfig.updateFrom(values);
13518 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013519 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013520 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013521 }
13522
Doug Zongker2bec3d42009-12-04 12:52:44 -080013523 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013524
Dianne Hackborn813075a62011-11-14 17:45:19 -080013525 if (values.locale != null && !initLocale) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013526 saveLocaleLocked(values.locale,
13527 !values.locale.equals(mConfiguration.locale),
13528 values.userSetLocale);
13529 }
13530
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013531 mConfigurationSeq++;
13532 if (mConfigurationSeq <= 0) {
13533 mConfigurationSeq = 1;
13534 }
13535 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013536 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013537 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn813075a62011-11-14 17:45:19 -080013538
Joe Onoratoe332aa12011-11-02 20:50:08 -070013539 // TODO: If our config changes, should we auto dismiss any currently
13540 // showing dialogs?
13541 mShowDialogs = shouldShowDialogs(newConfig);
13542
Dianne Hackborn813075a62011-11-14 17:45:19 -080013543 final Configuration configCopy = new Configuration(mConfiguration);
13544
Dianne Hackborn826d17c2009-11-12 12:55:51 -080013545 AttributeCache ac = AttributeCache.instance();
13546 if (ac != null) {
Dianne Hackborn813075a62011-11-14 17:45:19 -080013547 ac.updateConfiguration(configCopy);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080013548 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013549
Dianne Hackborn2f0b1752011-05-31 17:59:49 -070013550 // Make sure all resources in our process are updated
13551 // right now, so that anyone who is going to retrieve
13552 // resource values after we return will be sure to get
13553 // the new ones. This is especially important during
13554 // boot, where the first config change needs to guarantee
13555 // all resources have that config before following boot
13556 // code is executed.
Dianne Hackborn813075a62011-11-14 17:45:19 -080013557 mSystemThread.applyConfigurationToResources(configCopy);
Dianne Hackborn2f0b1752011-05-31 17:59:49 -070013558
Dianne Hackborn31ca8542011-07-19 14:58:28 -070013559 if (persistent && Settings.System.hasInterestingConfigurationChanges(changes)) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080013560 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
Dianne Hackborn813075a62011-11-14 17:45:19 -080013561 msg.obj = new Configuration(configCopy);
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080013562 mHandler.sendMessage(msg);
13563 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013564
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013565 for (int i=mLruProcesses.size()-1; i>=0; i--) {
13566 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013567 try {
13568 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013569 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013570 + app.processName + " new config " + mConfiguration);
Dianne Hackborn813075a62011-11-14 17:45:19 -080013571 app.thread.scheduleConfigurationChanged(configCopy);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013572 }
13573 } catch (Exception e) {
13574 }
13575 }
13576 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080013577 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
13578 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013579 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
13580 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080013581 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
13582 broadcastIntentLocked(null, null,
13583 new Intent(Intent.ACTION_LOCALE_CHANGED),
13584 null, null, 0, null, null,
13585 null, false, false, MY_PID, Process.SYSTEM_UID);
13586 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013587 }
13588 }
13589
13590 if (changes != 0 && starting == null) {
13591 // If the configuration changed, and the caller is not already
13592 // in the process of starting an activity, then find the top
13593 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013594 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013595 }
13596
13597 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013598 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
Dianne Hackborn5f4d6432010-12-21 20:40:11 -080013599 // And we need to make sure at this point that all other activities
13600 // are made visible with the correct configuration.
13601 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013602 }
13603
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013604 if (values != null && mWindowManager != null) {
13605 mWindowManager.setNewConfiguration(mConfiguration);
13606 }
13607
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013608 return kept;
13609 }
Joe Onoratoe332aa12011-11-02 20:50:08 -070013610
13611 /**
13612 * Decide based on the configuration whether we should shouw the ANR,
13613 * crash, etc dialogs. The idea is that if there is no affordnace to
13614 * press the on-screen buttons, we shouldn't show the dialog.
13615 *
13616 * A thought: SystemUI might also want to get told about this, the Power
13617 * dialog / global actions also might want different behaviors.
13618 */
13619 private static final boolean shouldShowDialogs(Configuration config) {
13620 return !(config.keyboard == Configuration.KEYBOARD_NOKEYS
13621 && config.touchscreen == Configuration.TOUCHSCREEN_NOTOUCH);
13622 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013623
13624 /**
13625 * Save the locale. You must be inside a synchronized (this) block.
13626 */
13627 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
13628 if(isDiff) {
13629 SystemProperties.set("user.language", l.getLanguage());
13630 SystemProperties.set("user.region", l.getCountry());
13631 }
13632
13633 if(isPersist) {
13634 SystemProperties.set("persist.sys.language", l.getLanguage());
13635 SystemProperties.set("persist.sys.country", l.getCountry());
13636 SystemProperties.set("persist.sys.localevar", l.getVariant());
13637 }
13638 }
13639
13640 // =========================================================
13641 // LIFETIME MANAGEMENT
13642 // =========================================================
13643
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013644 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
Dianne Hackborne02c88a2011-10-28 13:58:15 -070013645 ProcessRecord TOP_APP, boolean recursed, boolean doingAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013646 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013647 // This adjustment has already been computed. If we are calling
13648 // from the top, we may have already computed our adjustment with
13649 // an earlier hidden adjustment that isn't really for us... if
13650 // so, use the new hidden adjustment.
13651 if (!recursed && app.hidden) {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013652 app.curAdj = app.curRawAdj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013653 }
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013654 return app.curRawAdj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013655 }
13656
13657 if (app.thread == null) {
13658 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013659 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborne02c88a2011-10-28 13:58:15 -070013660 return (app.curAdj=ProcessList.HIDDEN_APP_MAX_ADJ);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013661 }
13662
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013663 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
13664 app.adjSource = null;
13665 app.adjTarget = null;
13666 app.empty = false;
13667 app.hidden = false;
13668
13669 final int activitiesSize = app.activities.size();
13670
Dianne Hackborn7d608422011-08-07 16:24:18 -070013671 if (app.maxAdj <= ProcessList.FOREGROUND_APP_ADJ) {
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013672 // The max adjustment doesn't allow this app to be anything
13673 // below foreground, so it is not worth doing work for it.
13674 app.adjType = "fixed";
13675 app.adjSeq = mAdjSeq;
13676 app.curRawAdj = app.maxAdj;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013677 app.foregroundActivities = false;
Dianne Hackborn287952c2010-09-22 22:34:31 -070013678 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013679 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013680 // System process can do UI, and when they do we want to have
13681 // them trim their memory after the user leaves the UI. To
13682 // facilitate this, here we need to determine whether or not it
13683 // is currently showing UI.
13684 app.systemNoUi = true;
13685 if (app == TOP_APP) {
13686 app.systemNoUi = false;
13687 } else if (activitiesSize > 0) {
13688 for (int j = 0; j < activitiesSize; j++) {
13689 final ActivityRecord r = app.activities.get(j);
13690 if (r.visible) {
13691 app.systemNoUi = false;
13692 break;
13693 }
13694 }
13695 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013696 return (app.curAdj=app.maxAdj);
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013697 }
13698
13699 final boolean hadForegroundActivities = app.foregroundActivities;
13700
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013701 app.foregroundActivities = false;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013702 app.keeping = false;
13703 app.systemNoUi = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013704
The Android Open Source Project4df24232009-03-05 14:34:35 -080013705 // Determine the importance of the process, starting with most
13706 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013707 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013708 int schedGroup;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013709 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013710 // The last app on the list is the foreground app.
Dianne Hackborn7d608422011-08-07 16:24:18 -070013711 adj = ProcessList.FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013712 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013713 app.adjType = "top-activity";
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013714 app.foregroundActivities = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013715 } else if (app.instrumentationClass != null) {
13716 // Don't want to kill running instrumentation.
Dianne Hackborn7d608422011-08-07 16:24:18 -070013717 adj = ProcessList.FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013718 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013719 app.adjType = "instrumentation";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013720 } else if (app.curReceiver != null ||
13721 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
13722 // An app that is currently receiving a broadcast also
13723 // counts as being in the foreground.
Dianne Hackborn7d608422011-08-07 16:24:18 -070013724 adj = ProcessList.FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013725 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013726 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013727 } else if (app.executingServices.size() > 0) {
13728 // An app that is currently executing a service callback also
13729 // counts as being in the foreground.
Dianne Hackborn7d608422011-08-07 16:24:18 -070013730 adj = ProcessList.FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013731 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013732 app.adjType = "exec-service";
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013733 } else if (activitiesSize > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013734 // This app is in the background with paused activities.
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013735 // We inspect activities to potentially upgrade adjustment further below.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013736 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013737 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013738 app.hidden = true;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013739 app.adjType = "bg-activities";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013740 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013741 // A very not-needed process. If this is lower in the lru list,
13742 // we will push it in to the empty bucket.
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013743 adj = hiddenAdj;
13744 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013745 app.hidden = true;
13746 app.empty = true;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013747 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013748 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013749
13750 // Examine all activities if not already foreground.
13751 if (!app.foregroundActivities && activitiesSize > 0) {
13752 for (int j = 0; j < activitiesSize; j++) {
13753 final ActivityRecord r = app.activities.get(j);
13754 if (r.visible) {
13755 // App has a visible activity; only upgrade adjustment.
Dianne Hackborn7d608422011-08-07 16:24:18 -070013756 if (adj > ProcessList.VISIBLE_APP_ADJ) {
13757 adj = ProcessList.VISIBLE_APP_ADJ;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013758 app.adjType = "visible";
13759 }
13760 schedGroup = Process.THREAD_GROUP_DEFAULT;
13761 app.hidden = false;
13762 app.foregroundActivities = true;
13763 break;
13764 } else if (r.state == ActivityState.PAUSING || r.state == ActivityState.PAUSED
13765 || r.state == ActivityState.STOPPING) {
13766 // Only upgrade adjustment.
Dianne Hackborn7d608422011-08-07 16:24:18 -070013767 if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
13768 adj = ProcessList.PERCEPTIBLE_APP_ADJ;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013769 app.adjType = "stopping";
13770 }
Dianne Hackborn8bf0aa92011-11-29 13:54:43 -080013771 app.hidden = false;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013772 app.foregroundActivities = true;
13773 }
13774 }
13775 }
13776
Dianne Hackborn7d608422011-08-07 16:24:18 -070013777 if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn83a6f452011-01-27 17:17:19 -080013778 if (app.foregroundServices) {
13779 // The user is aware of this app, so make it visible.
Dianne Hackborn7d608422011-08-07 16:24:18 -070013780 adj = ProcessList.PERCEPTIBLE_APP_ADJ;
Dianne Hackborn98cfebc2011-10-18 13:17:33 -070013781 app.hidden = false;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080013782 app.adjType = "foreground-service";
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013783 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080013784 } else if (app.forcingToForeground != null) {
13785 // The user is aware of this app, so make it visible.
Dianne Hackborn7d608422011-08-07 16:24:18 -070013786 adj = ProcessList.PERCEPTIBLE_APP_ADJ;
Dianne Hackborn98cfebc2011-10-18 13:17:33 -070013787 app.hidden = false;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080013788 app.adjType = "force-foreground";
13789 app.adjSource = app.forcingToForeground;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013790 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080013791 }
13792 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013793
Dianne Hackborn7d608422011-08-07 16:24:18 -070013794 if (adj > ProcessList.HEAVY_WEIGHT_APP_ADJ && app == mHeavyWeightProcess) {
Dianne Hackborn83a6f452011-01-27 17:17:19 -080013795 // We don't want to kill the current heavy-weight process.
Dianne Hackborn7d608422011-08-07 16:24:18 -070013796 adj = ProcessList.HEAVY_WEIGHT_APP_ADJ;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080013797 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborn98cfebc2011-10-18 13:17:33 -070013798 app.hidden = false;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080013799 app.adjType = "heavy";
13800 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013801
Dianne Hackborn7d608422011-08-07 16:24:18 -070013802 if (adj > ProcessList.HOME_APP_ADJ && app == mHomeProcess) {
Dianne Hackborn83a6f452011-01-27 17:17:19 -080013803 // This process is hosting what we currently consider to be the
13804 // home app, so we don't want to let it go into the background.
Dianne Hackborn7d608422011-08-07 16:24:18 -070013805 adj = ProcessList.HOME_APP_ADJ;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080013806 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborn98cfebc2011-10-18 13:17:33 -070013807 app.hidden = false;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080013808 app.adjType = "home";
13809 }
Dianne Hackborn98cfebc2011-10-18 13:17:33 -070013810
Dianne Hackbornf35fe232011-11-01 19:25:20 -070013811 if (adj > ProcessList.PREVIOUS_APP_ADJ && app == mPreviousProcess
13812 && app.activities.size() > 0) {
13813 // This was the previous process that showed UI to the user.
13814 // We want to try to keep it around more aggressively, to give
13815 // a good experience around switching between two apps.
13816 adj = ProcessList.PREVIOUS_APP_ADJ;
13817 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
13818 app.hidden = false;
13819 app.adjType = "previous";
13820 }
13821
Dianne Hackborn98cfebc2011-10-18 13:17:33 -070013822 if (false) Slog.i(TAG, "OOM " + app + ": initial adj=" + adj
13823 + " reason=" + app.adjType);
13824
The Android Open Source Project4df24232009-03-05 14:34:35 -080013825 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013826 // there are applications dependent on our services or providers, but
13827 // this gives us a baseline and makes sure we don't get into an
13828 // infinite recursion.
13829 app.adjSeq = mAdjSeq;
13830 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013831
Christopher Tate6fa95972009-06-05 18:43:55 -070013832 if (mBackupTarget != null && app == mBackupTarget.app) {
13833 // If possible we want to avoid killing apps while they're being backed up
Dianne Hackborn7d608422011-08-07 16:24:18 -070013834 if (adj > ProcessList.BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013835 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Dianne Hackborn7d608422011-08-07 16:24:18 -070013836 adj = ProcessList.BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013837 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013838 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070013839 }
13840 }
13841
Dianne Hackborn7d608422011-08-07 16:24:18 -070013842 if (app.services.size() != 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013843 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013844 final long now = SystemClock.uptimeMillis();
13845 // This process is more important if the top activity is
13846 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070013847 Iterator<ServiceRecord> jt = app.services.iterator();
Dianne Hackborn7d608422011-08-07 16:24:18 -070013848 while (jt.hasNext() && adj > ProcessList.FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070013849 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013850 if (s.startRequested) {
Dianne Hackborn98cfebc2011-10-18 13:17:33 -070013851 if (app.hasShownUi && app != mHomeProcess) {
Dianne Hackbornf0754f5b2011-07-21 16:02:07 -070013852 // If this process has shown some UI, let it immediately
13853 // go to the LRU list because it may be pretty heavy with
13854 // UI stuff. We'll tag it with a label just to help
13855 // debug and understand what is going on.
Dianne Hackborne02c88a2011-10-28 13:58:15 -070013856 if (adj > ProcessList.SERVICE_ADJ) {
Dianne Hackbornf0754f5b2011-07-21 16:02:07 -070013857 app.adjType = "started-bg-ui-services";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013858 }
Dianne Hackbornf0754f5b2011-07-21 16:02:07 -070013859 } else {
13860 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
13861 // This service has seen some activity within
13862 // recent memory, so we will keep its process ahead
13863 // of the background processes.
Dianne Hackborne02c88a2011-10-28 13:58:15 -070013864 if (adj > ProcessList.SERVICE_ADJ) {
13865 adj = ProcessList.SERVICE_ADJ;
Dianne Hackbornf0754f5b2011-07-21 16:02:07 -070013866 app.adjType = "started-services";
13867 app.hidden = false;
13868 }
13869 }
13870 // If we have let the service slide into the background
13871 // state, still have some text describing what it is doing
13872 // even though the service no longer has an impact.
Dianne Hackborne02c88a2011-10-28 13:58:15 -070013873 if (adj > ProcessList.SERVICE_ADJ) {
Dianne Hackbornf0754f5b2011-07-21 16:02:07 -070013874 app.adjType = "started-bg-services";
13875 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013876 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070013877 // Don't kill this process because it is doing work; it
13878 // has said it is doing work.
13879 app.keeping = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013880 }
Dianne Hackborn7d608422011-08-07 16:24:18 -070013881 if (s.connections.size() > 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013882 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070013883 Iterator<ArrayList<ConnectionRecord>> kt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013884 = s.connections.values().iterator();
Dianne Hackborn7d608422011-08-07 16:24:18 -070013885 while (kt.hasNext() && adj > ProcessList.FOREGROUND_APP_ADJ) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070013886 ArrayList<ConnectionRecord> clist = kt.next();
Dianne Hackborn7d608422011-08-07 16:24:18 -070013887 for (int i=0; i<clist.size() && adj > ProcessList.FOREGROUND_APP_ADJ; i++) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070013888 // XXX should compute this based on the max of
13889 // all connected clients.
13890 ConnectionRecord cr = clist.get(i);
13891 if (cr.binding.client == app) {
13892 // Binding to ourself is not interesting.
13893 continue;
13894 }
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013895 if ((cr.flags&Context.BIND_WAIVE_PRIORITY) == 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070013896 ProcessRecord client = cr.binding.client;
Dianne Hackborn130b0d22011-07-26 22:07:48 -070013897 int clientAdj = adj;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070013898 int myHiddenAdj = hiddenAdj;
13899 if (myHiddenAdj > client.hiddenAdj) {
Dianne Hackborn7d608422011-08-07 16:24:18 -070013900 if (client.hiddenAdj >= ProcessList.VISIBLE_APP_ADJ) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070013901 myHiddenAdj = client.hiddenAdj;
13902 } else {
Dianne Hackborn7d608422011-08-07 16:24:18 -070013903 myHiddenAdj = ProcessList.VISIBLE_APP_ADJ;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070013904 }
13905 }
Dianne Hackborn130b0d22011-07-26 22:07:48 -070013906 clientAdj = computeOomAdjLocked(
Dianne Hackborne02c88a2011-10-28 13:58:15 -070013907 client, myHiddenAdj, TOP_APP, true, doingAll);
Dianne Hackborn130b0d22011-07-26 22:07:48 -070013908 String adjType = null;
13909 if ((cr.flags&Context.BIND_ALLOW_OOM_MANAGEMENT) != 0) {
13910 // Not doing bind OOM management, so treat
13911 // this guy more like a started service.
Dianne Hackborn98cfebc2011-10-18 13:17:33 -070013912 if (app.hasShownUi && app != mHomeProcess) {
Dianne Hackborn130b0d22011-07-26 22:07:48 -070013913 // If this process has shown some UI, let it immediately
13914 // go to the LRU list because it may be pretty heavy with
13915 // UI stuff. We'll tag it with a label just to help
13916 // debug and understand what is going on.
13917 if (adj > clientAdj) {
13918 adjType = "bound-bg-ui-services";
13919 }
Dianne Hackborn98cfebc2011-10-18 13:17:33 -070013920 app.hidden = false;
Dianne Hackborn130b0d22011-07-26 22:07:48 -070013921 clientAdj = adj;
13922 } else {
13923 if (now >= (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
13924 // This service has not seen activity within
13925 // recent memory, so allow it to drop to the
13926 // LRU list if there is no other reason to keep
13927 // it around. We'll also tag it with a label just
13928 // to help debug and undertand what is going on.
13929 if (adj > clientAdj) {
13930 adjType = "bound-bg-services";
13931 }
13932 clientAdj = adj;
13933 }
13934 }
13935 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070013936 if (adj > clientAdj) {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013937 // If this process has recently shown UI, and
13938 // the process that is binding to it is less
13939 // important than being visible, then we don't
13940 // care about the binding as much as we care
13941 // about letting this process get into the LRU
13942 // list to be killed and restarted if needed for
13943 // memory.
Dianne Hackborn98cfebc2011-10-18 13:17:33 -070013944 if (app.hasShownUi && app != mHomeProcess
13945 && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013946 adjType = "bound-bg-ui-services";
13947 } else {
13948 if ((cr.flags&(Context.BIND_ABOVE_CLIENT
13949 |Context.BIND_IMPORTANT)) != 0) {
13950 adj = clientAdj;
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -070013951 } else if ((cr.flags&Context.BIND_NOT_VISIBLE) != 0
13952 && clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ
13953 && adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
13954 adj = ProcessList.PERCEPTIBLE_APP_ADJ;
13955 } else if (clientAdj > ProcessList.VISIBLE_APP_ADJ) {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013956 adj = clientAdj;
13957 } else {
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -070013958 app.pendingUiClean = true;
13959 if (adj > ProcessList.VISIBLE_APP_ADJ) {
13960 adj = ProcessList.VISIBLE_APP_ADJ;
13961 }
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013962 }
13963 if (!client.hidden) {
13964 app.hidden = false;
13965 }
13966 if (client.keeping) {
13967 app.keeping = true;
13968 }
13969 adjType = "service";
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070013970 }
Dianne Hackborn130b0d22011-07-26 22:07:48 -070013971 }
13972 if (adjType != null) {
13973 app.adjType = adjType;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070013974 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13975 .REASON_SERVICE_IN_USE;
13976 app.adjSource = cr.binding.client;
Dianne Hackborn905577f2011-09-07 18:31:28 -070013977 app.adjSourceOom = clientAdj;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070013978 app.adjTarget = s.name;
13979 }
13980 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
13981 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
13982 schedGroup = Process.THREAD_GROUP_DEFAULT;
13983 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013984 }
13985 }
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013986 if ((cr.flags&Context.BIND_ADJUST_WITH_ACTIVITY) != 0) {
13987 ActivityRecord a = cr.activity;
Dianne Hackborn7d608422011-08-07 16:24:18 -070013988 if (a != null && adj > ProcessList.FOREGROUND_APP_ADJ &&
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013989 (a.visible || a.state == ActivityState.RESUMED
13990 || a.state == ActivityState.PAUSING)) {
Dianne Hackborn7d608422011-08-07 16:24:18 -070013991 adj = ProcessList.FOREGROUND_APP_ADJ;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013992 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
13993 schedGroup = Process.THREAD_GROUP_DEFAULT;
13994 }
13995 app.hidden = false;
13996 app.adjType = "service";
13997 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13998 .REASON_SERVICE_IN_USE;
13999 app.adjSource = a;
Dianne Hackborn905577f2011-09-07 18:31:28 -070014000 app.adjSourceOom = adj;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014001 app.adjTarget = s.name;
14002 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014003 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014004 }
14005 }
14006 }
14007 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070014008
Dianne Hackborn287952c2010-09-22 22:34:31 -070014009 // Finally, if this process has active services running in it, we
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070014010 // would like to avoid killing it unless it would prevent the current
14011 // application from running. By default we put the process in
14012 // with the rest of the background processes; as we scan through
14013 // its services we may bump it up from there.
14014 if (adj > hiddenAdj) {
14015 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014016 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070014017 app.adjType = "bg-services";
14018 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014019 }
14020
Dianne Hackborn7d608422011-08-07 16:24:18 -070014021 if (app.pubProviders.size() != 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014022 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070014023 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn7d608422011-08-07 16:24:18 -070014024 while (jt.hasNext() && (adj > ProcessList.FOREGROUND_APP_ADJ
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014025 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070014026 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014027 if (cpr.clients.size() != 0) {
14028 Iterator<ProcessRecord> kt = cpr.clients.iterator();
Dianne Hackborn7d608422011-08-07 16:24:18 -070014029 while (kt.hasNext() && adj > ProcessList.FOREGROUND_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014030 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070014031 if (client == app) {
14032 // Being our own client is not interesting.
14033 continue;
14034 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014035 int myHiddenAdj = hiddenAdj;
14036 if (myHiddenAdj > client.hiddenAdj) {
Dianne Hackborn7d608422011-08-07 16:24:18 -070014037 if (client.hiddenAdj > ProcessList.FOREGROUND_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014038 myHiddenAdj = client.hiddenAdj;
14039 } else {
Dianne Hackborn7d608422011-08-07 16:24:18 -070014040 myHiddenAdj = ProcessList.FOREGROUND_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014041 }
14042 }
14043 int clientAdj = computeOomAdjLocked(
Dianne Hackborne02c88a2011-10-28 13:58:15 -070014044 client, myHiddenAdj, TOP_APP, true, doingAll);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014045 if (adj > clientAdj) {
Dianne Hackborn98cfebc2011-10-18 13:17:33 -070014046 if (app.hasShownUi && app != mHomeProcess
14047 && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014048 app.adjType = "bg-ui-provider";
14049 } else {
Dianne Hackborn7d608422011-08-07 16:24:18 -070014050 adj = clientAdj > ProcessList.FOREGROUND_APP_ADJ
14051 ? clientAdj : ProcessList.FOREGROUND_APP_ADJ;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014052 app.adjType = "provider";
14053 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014054 if (!client.hidden) {
14055 app.hidden = false;
14056 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070014057 if (client.keeping) {
14058 app.keeping = true;
14059 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070014060 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
14061 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014062 app.adjSource = client;
Dianne Hackborn905577f2011-09-07 18:31:28 -070014063 app.adjSourceOom = clientAdj;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070014064 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014065 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014066 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
14067 schedGroup = Process.THREAD_GROUP_DEFAULT;
14068 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014069 }
14070 }
14071 // If the provider has external (non-framework) process
14072 // dependencies, ensure that its adjustment is at least
14073 // FOREGROUND_APP_ADJ.
14074 if (cpr.externals != 0) {
Dianne Hackborn7d608422011-08-07 16:24:18 -070014075 if (adj > ProcessList.FOREGROUND_APP_ADJ) {
14076 adj = ProcessList.FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014077 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014078 app.hidden = false;
Dianne Hackborn287952c2010-09-22 22:34:31 -070014079 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014080 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070014081 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014082 }
14083 }
14084 }
14085 }
14086
14087 app.curRawAdj = adj;
14088
Joe Onorato8a9b2202010-02-26 18:56:32 -080014089 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014090 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
14091 if (adj > app.maxAdj) {
14092 adj = app.maxAdj;
Dianne Hackborn7d608422011-08-07 16:24:18 -070014093 if (app.maxAdj <= ProcessList.PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014094 schedGroup = Process.THREAD_GROUP_DEFAULT;
14095 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014096 }
Dianne Hackborn7d608422011-08-07 16:24:18 -070014097 if (adj < ProcessList.HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070014098 app.keeping = true;
14099 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014100
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014101 if (app.hasAboveClient) {
14102 // If this process has bound to any services with BIND_ABOVE_CLIENT,
14103 // then we need to drop its adjustment to be lower than the service's
14104 // in order to honor the request. We want to drop it by one adjustment
14105 // level... but there is special meaning applied to various levels so
14106 // we will skip some of them.
Dianne Hackborn7d608422011-08-07 16:24:18 -070014107 if (adj < ProcessList.FOREGROUND_APP_ADJ) {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014108 // System process will not get dropped, ever
Dianne Hackborn7d608422011-08-07 16:24:18 -070014109 } else if (adj < ProcessList.VISIBLE_APP_ADJ) {
14110 adj = ProcessList.VISIBLE_APP_ADJ;
14111 } else if (adj < ProcessList.PERCEPTIBLE_APP_ADJ) {
14112 adj = ProcessList.PERCEPTIBLE_APP_ADJ;
14113 } else if (adj < ProcessList.HIDDEN_APP_MIN_ADJ) {
14114 adj = ProcessList.HIDDEN_APP_MIN_ADJ;
Dianne Hackborne02c88a2011-10-28 13:58:15 -070014115 } else if (adj < ProcessList.HIDDEN_APP_MAX_ADJ) {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014116 adj++;
14117 }
14118 }
14119
Dianne Hackborne02c88a2011-10-28 13:58:15 -070014120 if (adj == ProcessList.SERVICE_ADJ) {
14121 if (doingAll) {
14122 app.serviceb = mNewNumServiceProcs > (mNumServiceProcs/3);
14123 mNewNumServiceProcs++;
14124 }
14125 if (app.serviceb) {
14126 adj = ProcessList.SERVICE_B_ADJ;
14127 }
14128 } else {
14129 app.serviceb = false;
14130 }
14131
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014132 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014133 app.curSchedGroup = schedGroup;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070014134
14135 if (hadForegroundActivities != app.foregroundActivities) {
Jeff Sharkey287bd832011-05-28 19:36:26 -070014136 mHandler.obtainMessage(DISPATCH_FOREGROUND_ACTIVITIES_CHANGED, app.pid, app.info.uid,
14137 app.foregroundActivities).sendToTarget();
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070014138 }
14139
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014140 return app.curRawAdj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014141 }
14142
14143 /**
14144 * Ask a given process to GC right now.
14145 */
14146 final void performAppGcLocked(ProcessRecord app) {
14147 try {
14148 app.lastRequestedGc = SystemClock.uptimeMillis();
14149 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014150 if (app.reportLowMemory) {
14151 app.reportLowMemory = false;
14152 app.thread.scheduleLowMemory();
14153 } else {
14154 app.thread.processInBackground();
14155 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014156 }
14157 } catch (Exception e) {
14158 // whatever.
14159 }
14160 }
14161
14162 /**
14163 * Returns true if things are idle enough to perform GCs.
14164 */
Josh Bartel7f208742010-02-25 11:01:44 -060014165 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014166 return mParallelBroadcasts.size() == 0
14167 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070014168 && (mSleeping || (mMainStack.mResumedActivity != null &&
14169 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014170 }
14171
14172 /**
14173 * Perform GCs on all processes that are waiting for it, but only
14174 * if things are idle.
14175 */
14176 final void performAppGcsLocked() {
14177 final int N = mProcessesToGc.size();
14178 if (N <= 0) {
14179 return;
14180 }
Josh Bartel7f208742010-02-25 11:01:44 -060014181 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014182 while (mProcessesToGc.size() > 0) {
14183 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn7d608422011-08-07 16:24:18 -070014184 if (proc.curRawAdj > ProcessList.PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014185 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
14186 <= SystemClock.uptimeMillis()) {
14187 // To avoid spamming the system, we will GC processes one
14188 // at a time, waiting a few seconds between each.
14189 performAppGcLocked(proc);
14190 scheduleAppGcsLocked();
14191 return;
14192 } else {
14193 // It hasn't been long enough since we last GCed this
14194 // process... put it in the list to wait for its time.
14195 addProcessToGcListLocked(proc);
14196 break;
14197 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014198 }
14199 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014200
14201 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014202 }
14203 }
14204
14205 /**
14206 * If all looks good, perform GCs on all processes waiting for them.
14207 */
14208 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060014209 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014210 performAppGcsLocked();
14211 return;
14212 }
14213 // Still not idle, wait some more.
14214 scheduleAppGcsLocked();
14215 }
14216
14217 /**
14218 * Schedule the execution of all pending app GCs.
14219 */
14220 final void scheduleAppGcsLocked() {
14221 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014222
14223 if (mProcessesToGc.size() > 0) {
14224 // Schedule a GC for the time to the next process.
14225 ProcessRecord proc = mProcessesToGc.get(0);
14226 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
14227
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014228 long when = proc.lastRequestedGc + GC_MIN_INTERVAL;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014229 long now = SystemClock.uptimeMillis();
14230 if (when < (now+GC_TIMEOUT)) {
14231 when = now + GC_TIMEOUT;
14232 }
14233 mHandler.sendMessageAtTime(msg, when);
14234 }
14235 }
14236
14237 /**
14238 * Add a process to the array of processes waiting to be GCed. Keeps the
14239 * list in sorted order by the last GC time. The process can't already be
14240 * on the list.
14241 */
14242 final void addProcessToGcListLocked(ProcessRecord proc) {
14243 boolean added = false;
14244 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
14245 if (mProcessesToGc.get(i).lastRequestedGc <
14246 proc.lastRequestedGc) {
14247 added = true;
14248 mProcessesToGc.add(i+1, proc);
14249 break;
14250 }
14251 }
14252 if (!added) {
14253 mProcessesToGc.add(0, proc);
14254 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014255 }
14256
14257 /**
14258 * Set up to ask a process to GC itself. This will either do it
14259 * immediately, or put it on the list of processes to gc the next
14260 * time things are idle.
14261 */
14262 final void scheduleAppGcLocked(ProcessRecord app) {
14263 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014264 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014265 return;
14266 }
14267 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014268 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014269 scheduleAppGcsLocked();
14270 }
14271 }
14272
Dianne Hackborn287952c2010-09-22 22:34:31 -070014273 final void checkExcessivePowerUsageLocked(boolean doKills) {
14274 updateCpuStatsNow();
14275
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070014276 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
Dianne Hackborn287952c2010-09-22 22:34:31 -070014277 boolean doWakeKills = doKills;
14278 boolean doCpuKills = doKills;
14279 if (mLastPowerCheckRealtime == 0) {
14280 doWakeKills = false;
14281 }
14282 if (mLastPowerCheckUptime == 0) {
14283 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070014284 }
14285 if (stats.isScreenOn()) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070014286 doWakeKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070014287 }
14288 final long curRealtime = SystemClock.elapsedRealtime();
Dianne Hackborn287952c2010-09-22 22:34:31 -070014289 final long realtimeSince = curRealtime - mLastPowerCheckRealtime;
14290 final long curUptime = SystemClock.uptimeMillis();
14291 final long uptimeSince = curUptime - mLastPowerCheckUptime;
14292 mLastPowerCheckRealtime = curRealtime;
14293 mLastPowerCheckUptime = curUptime;
14294 if (realtimeSince < WAKE_LOCK_MIN_CHECK_DURATION) {
14295 doWakeKills = false;
14296 }
14297 if (uptimeSince < CPU_MIN_CHECK_DURATION) {
14298 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070014299 }
14300 int i = mLruProcesses.size();
14301 while (i > 0) {
14302 i--;
14303 ProcessRecord app = mLruProcesses.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -070014304 if (!app.keeping) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070014305 long wtime;
14306 synchronized (stats) {
14307 wtime = stats.getProcessWakeTime(app.info.uid,
14308 app.pid, curRealtime);
14309 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070014310 long wtimeUsed = wtime - app.lastWakeTime;
14311 long cputimeUsed = app.curCpuTime - app.lastCpuTime;
14312 if (DEBUG_POWER) {
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070014313 StringBuilder sb = new StringBuilder(128);
14314 sb.append("Wake for ");
14315 app.toShortString(sb);
14316 sb.append(": over ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070014317 TimeUtils.formatDuration(realtimeSince, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070014318 sb.append(" used ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070014319 TimeUtils.formatDuration(wtimeUsed, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070014320 sb.append(" (");
Dianne Hackborn287952c2010-09-22 22:34:31 -070014321 sb.append((wtimeUsed*100)/realtimeSince);
14322 sb.append("%)");
14323 Slog.i(TAG, sb.toString());
14324 sb.setLength(0);
14325 sb.append("CPU for ");
14326 app.toShortString(sb);
14327 sb.append(": over ");
14328 TimeUtils.formatDuration(uptimeSince, sb);
14329 sb.append(" used ");
14330 TimeUtils.formatDuration(cputimeUsed, sb);
14331 sb.append(" (");
14332 sb.append((cputimeUsed*100)/uptimeSince);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070014333 sb.append("%)");
14334 Slog.i(TAG, sb.toString());
14335 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070014336 // If a process has held a wake lock for more
14337 // than 50% of the time during this period,
14338 // that sounds pad. Kill!
Dianne Hackborn287952c2010-09-22 22:34:31 -070014339 if (doWakeKills && realtimeSince > 0
14340 && ((wtimeUsed*100)/realtimeSince) >= 50) {
14341 synchronized (stats) {
14342 stats.reportExcessiveWakeLocked(app.info.uid, app.processName,
14343 realtimeSince, wtimeUsed);
14344 }
14345 Slog.w(TAG, "Excessive wake lock in " + app.processName
14346 + " (pid " + app.pid + "): held " + wtimeUsed
14347 + " during " + realtimeSince);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070014348 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
14349 app.processName, app.setAdj, "excessive wake lock");
14350 Process.killProcessQuiet(app.pid);
Dianne Hackborn287952c2010-09-22 22:34:31 -070014351 } else if (doCpuKills && uptimeSince > 0
14352 && ((cputimeUsed*100)/uptimeSince) >= 50) {
14353 synchronized (stats) {
14354 stats.reportExcessiveCpuLocked(app.info.uid, app.processName,
14355 uptimeSince, cputimeUsed);
14356 }
14357 Slog.w(TAG, "Excessive CPU in " + app.processName
14358 + " (pid " + app.pid + "): used " + cputimeUsed
14359 + " during " + uptimeSince);
14360 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
14361 app.processName, app.setAdj, "excessive cpu");
14362 Process.killProcessQuiet(app.pid);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070014363 } else {
14364 app.lastWakeTime = wtime;
Dianne Hackborn287952c2010-09-22 22:34:31 -070014365 app.lastCpuTime = app.curCpuTime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070014366 }
14367 }
14368 }
14369 }
14370
Dianne Hackborn295e3c22011-08-25 13:19:08 -070014371 private final boolean updateOomAdjLocked(
Dianne Hackborne02c88a2011-10-28 13:58:15 -070014372 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP, boolean doingAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014373 app.hiddenAdj = hiddenAdj;
14374
14375 if (app.thread == null) {
Dianne Hackborn295e3c22011-08-25 13:19:08 -070014376 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014377 }
14378
Dianne Hackborn287952c2010-09-22 22:34:31 -070014379 final boolean wasKeeping = app.keeping;
14380
Dianne Hackborn295e3c22011-08-25 13:19:08 -070014381 boolean success = true;
14382
Dianne Hackborne02c88a2011-10-28 13:58:15 -070014383 computeOomAdjLocked(app, hiddenAdj, TOP_APP, false, doingAll);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014384
Jeff Brown10e89712011-07-08 18:52:57 -070014385 if (app.curRawAdj != app.setRawAdj) {
Dianne Hackborn905577f2011-09-07 18:31:28 -070014386 if (false) {
14387 // Removing for now. Forcing GCs is not so useful anymore
14388 // with Dalvik, and the new memory level hint facility is
14389 // better for what we need to do these days.
14390 if (app.curRawAdj > ProcessList.FOREGROUND_APP_ADJ
14391 && app.setRawAdj <= ProcessList.FOREGROUND_APP_ADJ) {
14392 // If this app is transitioning from foreground to
14393 // non-foreground, have it do a gc.
14394 scheduleAppGcLocked(app);
14395 } else if (app.curRawAdj >= ProcessList.HIDDEN_APP_MIN_ADJ
14396 && app.setRawAdj < ProcessList.HIDDEN_APP_MIN_ADJ) {
14397 // Likewise do a gc when an app is moving in to the
14398 // background (such as a service stopping).
14399 scheduleAppGcLocked(app);
14400 }
Jeff Brown10e89712011-07-08 18:52:57 -070014401 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070014402
Jeff Brown10e89712011-07-08 18:52:57 -070014403 if (wasKeeping && !app.keeping) {
14404 // This app is no longer something we want to keep. Note
14405 // its current wake lock time to later know to kill it if
14406 // it is not behaving well.
14407 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
14408 synchronized (stats) {
14409 app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
14410 app.pid, SystemClock.elapsedRealtime());
14411 }
14412 app.lastCpuTime = app.curCpuTime;
14413 }
14414
14415 app.setRawAdj = app.curRawAdj;
14416 }
Dianne Hackborne02c88a2011-10-28 13:58:15 -070014417
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014418 if (app.curAdj != app.setAdj) {
14419 if (Process.setOomAdj(app.pid, app.curAdj)) {
Dianne Hackbornbbb09ac2011-11-30 11:31:29 -080014420 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
Dianne Hackborne02c88a2011-10-28 13:58:15 -070014421 TAG, "Set " + app.pid + " " + app.processName +
14422 " adj " + app.curAdj + ": " + app.adjType);
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014423 app.setAdj = app.curAdj;
Jeff Brown10e89712011-07-08 18:52:57 -070014424 } else {
Dianne Hackborn295e3c22011-08-25 13:19:08 -070014425 success = false;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014426 Slog.w(TAG, "Failed setting oom adj of " + app + " to " + app.curAdj);
Jeff Brown10e89712011-07-08 18:52:57 -070014427 }
14428 }
14429 if (app.setSchedGroup != app.curSchedGroup) {
14430 app.setSchedGroup = app.curSchedGroup;
14431 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
14432 "Setting process group of " + app.processName
14433 + " to " + app.curSchedGroup);
14434 if (app.waitingToKill != null &&
14435 app.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {
14436 Slog.i(TAG, "Killing " + app.toShortString() + ": " + app.waitingToKill);
14437 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
14438 app.processName, app.setAdj, app.waitingToKill);
14439 Process.killProcessQuiet(app.pid);
Dianne Hackborn295e3c22011-08-25 13:19:08 -070014440 success = false;
Jeff Brown10e89712011-07-08 18:52:57 -070014441 } else {
14442 if (true) {
14443 long oldId = Binder.clearCallingIdentity();
14444 try {
14445 Process.setProcessGroup(app.pid, app.curSchedGroup);
14446 } catch (Exception e) {
14447 Slog.w(TAG, "Failed setting process group of " + app.pid
14448 + " to " + app.curSchedGroup);
14449 e.printStackTrace();
14450 } finally {
14451 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070014452 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014453 } else {
Jeff Brown10e89712011-07-08 18:52:57 -070014454 if (app.thread != null) {
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014455 try {
Jeff Brown10e89712011-07-08 18:52:57 -070014456 app.thread.setSchedulingGroup(app.curSchedGroup);
14457 } catch (RemoteException e) {
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014458 }
14459 }
14460 }
14461 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014462 }
Dianne Hackborn295e3c22011-08-25 13:19:08 -070014463 return success;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014464 }
14465
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070014466 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070014467 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014468 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070014469 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014470 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070014471 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014472 }
14473 }
14474 return resumedActivity;
14475 }
14476
Dianne Hackborn295e3c22011-08-25 13:19:08 -070014477 private final boolean updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070014478 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014479 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
14480 int curAdj = app.curAdj;
Dianne Hackborn7d608422011-08-07 16:24:18 -070014481 final boolean wasHidden = curAdj >= ProcessList.HIDDEN_APP_MIN_ADJ
14482 && curAdj <= ProcessList.HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014483
14484 mAdjSeq++;
14485
Dianne Hackborne02c88a2011-10-28 13:58:15 -070014486 boolean success = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP, false);
Dianne Hackborn7d608422011-08-07 16:24:18 -070014487 final boolean nowHidden = app.curAdj >= ProcessList.HIDDEN_APP_MIN_ADJ
14488 && app.curAdj <= ProcessList.HIDDEN_APP_MAX_ADJ;
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014489 if (nowHidden != wasHidden) {
14490 // Changed to/from hidden state, so apps after it in the LRU
14491 // list may also be changed.
14492 updateOomAdjLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014493 }
Dianne Hackborn295e3c22011-08-25 13:19:08 -070014494 return success;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014495 }
14496
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014497 final void updateOomAdjLocked() {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070014498 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014499 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
14500
14501 if (false) {
14502 RuntimeException e = new RuntimeException();
14503 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080014504 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014505 }
14506
14507 mAdjSeq++;
Dianne Hackborne02c88a2011-10-28 13:58:15 -070014508 mNewNumServiceProcs = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014509
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014510 // Let's determine how many processes we have running vs.
14511 // how many slots we have for background processes; we may want
14512 // to put multiple processes in a slot of there are enough of
14513 // them.
Dianne Hackborn7d608422011-08-07 16:24:18 -070014514 int numSlots = ProcessList.HIDDEN_APP_MAX_ADJ - ProcessList.HIDDEN_APP_MIN_ADJ + 1;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014515 int factor = (mLruProcesses.size()-4)/numSlots;
14516 if (factor < 1) factor = 1;
14517 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070014518 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014519
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014520 // First update the OOM adjustment for each of the
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014521 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014522 int i = mLruProcesses.size();
Dianne Hackborn7d608422011-08-07 16:24:18 -070014523 int curHiddenAdj = ProcessList.HIDDEN_APP_MIN_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014524 while (i > 0) {
14525 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014526 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080014527 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
Dianne Hackborne02c88a2011-10-28 13:58:15 -070014528 updateOomAdjLocked(app, curHiddenAdj, TOP_APP, true);
14529 if (curHiddenAdj < ProcessList.HIDDEN_APP_MAX_ADJ
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014530 && app.curAdj == curHiddenAdj) {
14531 step++;
14532 if (step >= factor) {
14533 step = 0;
14534 curHiddenAdj++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014535 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014536 }
14537 if (!app.killedBackground) {
Dianne Hackborn7d608422011-08-07 16:24:18 -070014538 if (app.curAdj >= ProcessList.HIDDEN_APP_MIN_ADJ) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014539 numHidden++;
14540 if (numHidden > mProcessLimit) {
14541 Slog.i(TAG, "No longer want " + app.processName
14542 + " (pid " + app.pid + "): hidden #" + numHidden);
14543 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
14544 app.processName, app.setAdj, "too many background");
14545 app.killedBackground = true;
14546 Process.killProcessQuiet(app.pid);
Dianne Hackborn8633e682010-04-22 16:03:41 -070014547 }
14548 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014549 }
14550 }
14551
Dianne Hackborne02c88a2011-10-28 13:58:15 -070014552 mNumServiceProcs = mNewNumServiceProcs;
14553
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014554 // Now determine the memory trimming level of background processes.
14555 // Unfortunately we need to start at the back of the list to do this
14556 // properly. We only do this if the number of background apps we
14557 // are managing to keep around is less than half the maximum we desire;
14558 // if we are keeping a good number around, we'll let them use whatever
14559 // memory they want.
Dianne Hackborn7d608422011-08-07 16:24:18 -070014560 if (numHidden <= (ProcessList.MAX_HIDDEN_APPS/2)) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014561 final int N = mLruProcesses.size();
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080014562 factor = numHidden/3;
14563 int minFactor = 2;
14564 if (mHomeProcess != null) minFactor++;
14565 if (mPreviousProcess != null) minFactor++;
14566 if (factor < minFactor) factor = minFactor;
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014567 step = 0;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014568 int curLevel = ComponentCallbacks2.TRIM_MEMORY_COMPLETE;
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014569 for (i=0; i<N; i++) {
14570 ProcessRecord app = mLruProcesses.get(i);
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080014571 if (app.curAdj >= ProcessList.HOME_APP_ADJ
14572 && app.curAdj != ProcessList.SERVICE_B_ADJ
14573 && !app.killedBackground) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014574 if (app.trimMemoryLevel < curLevel && app.thread != null) {
14575 try {
14576 app.thread.scheduleTrimMemory(curLevel);
14577 } catch (RemoteException e) {
14578 }
Dianne Hackborn77eaaf02011-12-05 18:05:31 -080014579 if (false) {
14580 // For now we won't do this; our memory trimming seems
14581 // to be good enough at this point that destroying
14582 // activities causes more harm than good.
14583 if (curLevel >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE
14584 && app != mHomeProcess && app != mPreviousProcess) {
14585 // For these apps we will also finish their activities
14586 // to help them free memory.
14587 mMainStack.destroyActivitiesLocked(app, false, "trim");
14588 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014589 }
14590 }
14591 app.trimMemoryLevel = curLevel;
14592 step++;
14593 if (step >= factor) {
14594 switch (curLevel) {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014595 case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:
14596 curLevel = ComponentCallbacks2.TRIM_MEMORY_MODERATE;
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014597 break;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014598 case ComponentCallbacks2.TRIM_MEMORY_MODERATE:
14599 curLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014600 break;
14601 }
14602 }
Dianne Hackborn7d608422011-08-07 16:24:18 -070014603 } else if (app.curAdj == ProcessList.HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014604 if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_BACKGROUND
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014605 && app.thread != null) {
14606 try {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014607 app.thread.scheduleTrimMemory(
14608 ComponentCallbacks2.TRIM_MEMORY_BACKGROUND);
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014609 } catch (RemoteException e) {
14610 }
14611 }
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014612 app.trimMemoryLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
Dianne Hackborn7d608422011-08-07 16:24:18 -070014613 } else if ((app.curAdj > ProcessList.VISIBLE_APP_ADJ || app.systemNoUi)
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014614 && app.pendingUiClean) {
14615 if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN
14616 && app.thread != null) {
14617 try {
14618 app.thread.scheduleTrimMemory(
14619 ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
14620 } catch (RemoteException e) {
14621 }
14622 }
14623 app.trimMemoryLevel = ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN;
14624 app.pendingUiClean = false;
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014625 } else {
14626 app.trimMemoryLevel = 0;
14627 }
14628 }
14629 } else {
14630 final int N = mLruProcesses.size();
14631 for (i=0; i<N; i++) {
14632 ProcessRecord app = mLruProcesses.get(i);
Dianne Hackborn7d608422011-08-07 16:24:18 -070014633 if ((app.curAdj > ProcessList.VISIBLE_APP_ADJ || app.systemNoUi)
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014634 && app.pendingUiClean) {
14635 if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN
14636 && app.thread != null) {
14637 try {
14638 app.thread.scheduleTrimMemory(
14639 ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
14640 } catch (RemoteException e) {
14641 }
14642 }
14643 app.trimMemoryLevel = ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN;
14644 app.pendingUiClean = false;
14645 } else {
14646 app.trimMemoryLevel = 0;
14647 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014648 }
14649 }
14650
14651 if (mAlwaysFinishActivities) {
Dianne Hackborn28695e02011-11-02 21:59:51 -070014652 mMainStack.destroyActivitiesLocked(null, false, "always-finish");
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014653 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014654 }
14655
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070014656 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014657 synchronized (this) {
14658 int i;
14659
14660 // First remove any unused application processes whose package
14661 // has been removed.
14662 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
14663 final ProcessRecord app = mRemovedProcesses.get(i);
14664 if (app.activities.size() == 0
14665 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014666 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014667 TAG, "Exiting empty application process "
14668 + app.processName + " ("
14669 + (app.thread != null ? app.thread.asBinder() : null)
14670 + ")\n");
14671 if (app.pid > 0 && app.pid != MY_PID) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070014672 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
14673 app.processName, app.setAdj, "empty");
14674 Process.killProcessQuiet(app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014675 } else {
14676 try {
14677 app.thread.scheduleExit();
14678 } catch (Exception e) {
14679 // Ignore exceptions.
14680 }
14681 }
Dianne Hackborn130b0d22011-07-26 22:07:48 -070014682 cleanUpApplicationRecordLocked(app, false, true, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014683 mRemovedProcesses.remove(i);
14684
14685 if (app.persistent) {
14686 if (app.persistent) {
14687 addAppLocked(app.info);
14688 }
14689 }
14690 }
14691 }
14692
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014693 // Now update the oom adj for all processes.
14694 updateOomAdjLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014695 }
14696 }
14697
14698 /** This method sends the specified signal to each of the persistent apps */
14699 public void signalPersistentProcesses(int sig) throws RemoteException {
14700 if (sig != Process.SIGNAL_USR1) {
14701 throw new SecurityException("Only SIGNAL_USR1 is allowed");
14702 }
14703
14704 synchronized (this) {
14705 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
14706 != PackageManager.PERMISSION_GRANTED) {
14707 throw new SecurityException("Requires permission "
14708 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
14709 }
14710
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014711 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
14712 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014713 if (r.thread != null && r.persistent) {
14714 Process.sendSignal(r.pid, sig);
14715 }
14716 }
14717 }
14718 }
14719
Dianne Hackborn62f20ec2011-08-15 17:40:28 -070014720 private void stopProfilerLocked(ProcessRecord proc, String path, int profileType) {
14721 if (proc == null || proc == mProfileProc) {
14722 proc = mProfileProc;
14723 path = mProfileFile;
14724 profileType = mProfileType;
14725 clearProfilerLocked();
14726 }
14727 if (proc == null) {
14728 return;
14729 }
14730 try {
14731 proc.thread.profilerControl(false, path, null, profileType);
14732 } catch (RemoteException e) {
14733 throw new IllegalStateException("Process disappeared");
14734 }
14735 }
14736
14737 private void clearProfilerLocked() {
14738 if (mProfileFd != null) {
14739 try {
14740 mProfileFd.close();
14741 } catch (IOException e) {
14742 }
14743 }
14744 mProfileApp = null;
14745 mProfileProc = null;
14746 mProfileFile = null;
14747 mProfileType = 0;
14748 mAutoStopProfiler = false;
14749 }
14750
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014751 public boolean profileControl(String process, boolean start,
Romain Guy7eabe552011-07-21 14:56:34 -070014752 String path, ParcelFileDescriptor fd, int profileType) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014753
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014754 try {
14755 synchronized (this) {
14756 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
14757 // its own permission.
14758 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
14759 != PackageManager.PERMISSION_GRANTED) {
14760 throw new SecurityException("Requires permission "
14761 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014762 }
Dianne Hackborn62f20ec2011-08-15 17:40:28 -070014763
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014764 if (start && fd == null) {
14765 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014766 }
Dianne Hackborn62f20ec2011-08-15 17:40:28 -070014767
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014768 ProcessRecord proc = null;
Dianne Hackborn62f20ec2011-08-15 17:40:28 -070014769 if (process != null) {
14770 try {
14771 int pid = Integer.parseInt(process);
14772 synchronized (mPidsSelfLocked) {
14773 proc = mPidsSelfLocked.get(pid);
14774 }
14775 } catch (NumberFormatException e) {
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014776 }
Dianne Hackborn62f20ec2011-08-15 17:40:28 -070014777
14778 if (proc == null) {
14779 HashMap<String, SparseArray<ProcessRecord>> all
14780 = mProcessNames.getMap();
14781 SparseArray<ProcessRecord> procs = all.get(process);
14782 if (procs != null && procs.size() > 0) {
14783 proc = procs.valueAt(0);
14784 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014785 }
14786 }
Dianne Hackborn62f20ec2011-08-15 17:40:28 -070014787
14788 if (start && (proc == null || proc.thread == null)) {
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014789 throw new IllegalArgumentException("Unknown process: " + process);
14790 }
Dianne Hackborn62f20ec2011-08-15 17:40:28 -070014791
14792 if (start) {
14793 stopProfilerLocked(null, null, 0);
14794 setProfileApp(proc.info, proc.processName, path, fd, false);
14795 mProfileProc = proc;
14796 mProfileType = profileType;
14797 try {
14798 fd = fd.dup();
14799 } catch (IOException e) {
14800 fd = null;
14801 }
14802 proc.thread.profilerControl(start, path, fd, profileType);
14803 fd = null;
14804 mProfileFd = null;
14805 } else {
14806 stopProfilerLocked(proc, path, profileType);
14807 if (fd != null) {
14808 try {
14809 fd.close();
14810 } catch (IOException e) {
14811 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014812 }
14813 }
Dianne Hackborn62f20ec2011-08-15 17:40:28 -070014814
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014815 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014816 }
14817 } catch (RemoteException e) {
14818 throw new IllegalStateException("Process disappeared");
14819 } finally {
14820 if (fd != null) {
14821 try {
14822 fd.close();
14823 } catch (IOException e) {
14824 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014825 }
14826 }
14827 }
Andy McFadden824c5102010-07-09 16:26:57 -070014828
14829 public boolean dumpHeap(String process, boolean managed,
14830 String path, ParcelFileDescriptor fd) throws RemoteException {
14831
14832 try {
14833 synchronized (this) {
14834 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
14835 // its own permission (same as profileControl).
14836 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
14837 != PackageManager.PERMISSION_GRANTED) {
14838 throw new SecurityException("Requires permission "
14839 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
14840 }
14841
14842 if (fd == null) {
14843 throw new IllegalArgumentException("null fd");
14844 }
14845
14846 ProcessRecord proc = null;
14847 try {
14848 int pid = Integer.parseInt(process);
14849 synchronized (mPidsSelfLocked) {
14850 proc = mPidsSelfLocked.get(pid);
14851 }
14852 } catch (NumberFormatException e) {
14853 }
14854
14855 if (proc == null) {
14856 HashMap<String, SparseArray<ProcessRecord>> all
14857 = mProcessNames.getMap();
14858 SparseArray<ProcessRecord> procs = all.get(process);
14859 if (procs != null && procs.size() > 0) {
14860 proc = procs.valueAt(0);
14861 }
14862 }
14863
14864 if (proc == null || proc.thread == null) {
14865 throw new IllegalArgumentException("Unknown process: " + process);
14866 }
14867
Dianne Hackbornf02e57b2011-03-01 22:21:04 -080014868 boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
14869 if (!isDebuggable) {
Andy McFadden824c5102010-07-09 16:26:57 -070014870 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
14871 throw new SecurityException("Process not debuggable: " + proc);
14872 }
14873 }
14874
14875 proc.thread.dumpHeap(managed, path, fd);
14876 fd = null;
14877 return true;
14878 }
14879 } catch (RemoteException e) {
14880 throw new IllegalStateException("Process disappeared");
14881 } finally {
14882 if (fd != null) {
14883 try {
14884 fd.close();
14885 } catch (IOException e) {
14886 }
14887 }
14888 }
14889 }
14890
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014891 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
14892 public void monitor() {
14893 synchronized (this) { }
14894 }
Svetoslav Ganov54d068e2011-03-02 12:58:40 -080014895
14896 public void onCoreSettingsChange(Bundle settings) {
14897 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
14898 ProcessRecord processRecord = mLruProcesses.get(i);
14899 try {
14900 if (processRecord.thread != null) {
14901 processRecord.thread.setCoreSettings(settings);
14902 }
14903 } catch (RemoteException re) {
14904 /* ignore */
14905 }
14906 }
14907 }
Amith Yamasani4b2e9342011-03-31 12:38:53 -070014908
14909 // Multi-user methods
14910
14911 public boolean switchUser(int userid) {
14912 // TODO
14913 return true;
14914 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014915}