blob: 0d6f405136dd516fc1ade381326d0708c83c127c [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006-2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.am;
18
Dianne Hackborn860755f2010-06-03 18:47:52 -070019import com.android.internal.R;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080020import com.android.internal.os.BatteryStatsImpl;
Dianne Hackborn45ce8642011-07-14 16:10:16 -070021import com.android.internal.os.ProcessStats;
Dianne Hackbornde7faf62009-06-30 13:27:30 -070022import com.android.server.AttributeCache;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080023import com.android.server.IntentResolver;
24import com.android.server.ProcessMap;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080025import com.android.server.SystemServer;
26import com.android.server.Watchdog;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070027import com.android.server.am.ActivityStack.ActivityState;
Dianne Hackborna924dc0d2011-02-17 14:22:17 -080028import com.android.server.wm.WindowManagerService;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029
Dianne Hackborndd71fc82009-12-16 19:24:32 -080030import dalvik.system.Zygote;
31
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032import android.app.Activity;
33import android.app.ActivityManager;
34import android.app.ActivityManagerNative;
35import android.app.ActivityThread;
36import android.app.AlertDialog;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070037import android.app.AppGlobals;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020038import android.app.ApplicationErrorReport;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039import android.app.Dialog;
Dianne Hackbornb06ea702009-07-13 13:07:51 -070040import android.app.IActivityController;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041import android.app.IActivityWatcher;
42import android.app.IApplicationThread;
43import android.app.IInstrumentationWatcher;
Dianne Hackborn860755f2010-06-03 18:47:52 -070044import android.app.INotificationManager;
Jeff Sharkeya4620792011-05-20 15:29:23 -070045import android.app.IProcessObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046import android.app.IServiceConnection;
47import android.app.IThumbnailReceiver;
48import android.app.Instrumentation;
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070049import android.app.Notification;
Dianne Hackborn860755f2010-06-03 18:47:52 -070050import android.app.NotificationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080051import android.app.PendingIntent;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070052import android.app.Service;
Christopher Tate45281862010-03-05 15:46:30 -080053import android.app.backup.IBackupManager;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020054import android.content.ActivityNotFoundException;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080055import android.content.BroadcastReceiver;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070056import android.content.ComponentCallbacks2;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080057import android.content.ComponentName;
58import android.content.ContentResolver;
59import android.content.Context;
Christian Mehlmauer7664e202010-07-20 08:46:17 +020060import android.content.DialogInterface;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080061import android.content.Intent;
62import android.content.IntentFilter;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070063import android.content.IIntentReceiver;
64import android.content.IIntentSender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -070065import android.content.IntentSender;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080066import android.content.pm.ActivityInfo;
67import android.content.pm.ApplicationInfo;
68import android.content.pm.ConfigurationInfo;
69import android.content.pm.IPackageDataObserver;
70import android.content.pm.IPackageManager;
71import android.content.pm.InstrumentationInfo;
Dan Egnor66c40e72010-01-26 16:23:11 -080072import android.content.pm.PackageInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080073import android.content.pm.PackageManager;
Dianne Hackborn2af632f2009-07-08 14:56:37 -070074import android.content.pm.PathPermission;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080075import android.content.pm.ProviderInfo;
76import android.content.pm.ResolveInfo;
77import android.content.pm.ServiceInfo;
Dianne Hackborn860755f2010-06-03 18:47:52 -070078import android.content.pm.PackageManager.NameNotFoundException;
Dianne Hackborne2515ee2011-04-27 18:52:56 -040079import android.content.res.CompatibilityInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080080import android.content.res.Configuration;
81import android.graphics.Bitmap;
Robert Greenwalt434203a2010-10-11 16:00:27 -070082import android.net.Proxy;
83import android.net.ProxyProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080084import android.net.Uri;
85import android.os.Binder;
Dan Egnor60d87622009-12-16 16:32:58 -080086import android.os.Build;
Dan Egnor42471dd2010-01-07 17:25:22 -080087import android.os.Bundle;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070088import android.os.Debug;
Dan Egnor60d87622009-12-16 16:32:58 -080089import android.os.DropBoxManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080090import android.os.Environment;
Dan Egnor42471dd2010-01-07 17:25:22 -080091import android.os.FileObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080092import android.os.FileUtils;
93import android.os.Handler;
94import android.os.IBinder;
95import android.os.IPermissionController;
96import android.os.Looper;
97import android.os.Message;
98import android.os.Parcel;
99import android.os.ParcelFileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800100import android.os.Process;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700101import android.os.RemoteCallbackList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102import android.os.RemoteException;
103import android.os.ServiceManager;
Brad Fitzpatrick46d42382010-06-11 13:57:58 -0700104import android.os.StrictMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800105import android.os.SystemClock;
106import android.os.SystemProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800107import android.provider.Settings;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800108import android.util.EventLog;
Dianne Hackborn905577f2011-09-07 18:31:28 -0700109import android.util.Pair;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800110import android.util.Slog;
Joe Onorato5d3bea62010-03-01 13:44:29 -0800111import android.util.Log;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800112import android.util.PrintWriterPrinter;
113import android.util.SparseArray;
Dianne Hackborn1ebccf52010-08-15 13:04:34 -0700114import android.util.TimeUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800115import android.view.Gravity;
116import android.view.LayoutInflater;
117import android.view.View;
118import android.view.WindowManager;
119import android.view.WindowManagerPolicy;
120
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700121import java.io.BufferedInputStream;
122import java.io.BufferedOutputStream;
123import java.io.DataInputStream;
124import java.io.DataOutputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800125import java.io.File;
126import java.io.FileDescriptor;
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700127import java.io.FileInputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800128import java.io.FileNotFoundException;
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700129import java.io.FileOutputStream;
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200130import java.io.IOException;
Dan Egnora455d192010-03-12 08:52:28 -0800131import java.io.InputStreamReader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800132import java.io.PrintWriter;
133import java.lang.IllegalStateException;
134import java.lang.ref.WeakReference;
135import java.util.ArrayList;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700136import java.util.Collections;
137import java.util.Comparator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800138import java.util.HashMap;
139import java.util.HashSet;
140import java.util.Iterator;
141import java.util.List;
142import java.util.Locale;
143import java.util.Map;
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -0700144import java.util.Set;
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700145import java.util.concurrent.atomic.AtomicBoolean;
146import java.util.concurrent.atomic.AtomicLong;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800147
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700148public final class ActivityManagerService extends ActivityManagerNative
149 implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800150 static final String TAG = "ActivityManager";
151 static final boolean DEBUG = false;
Dianne Hackborne2515ee2011-04-27 18:52:56 -0400152 static final boolean localLOGV = DEBUG;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800153 static final boolean DEBUG_SWITCH = localLOGV || false;
154 static final boolean DEBUG_TASKS = localLOGV || false;
155 static final boolean DEBUG_PAUSE = localLOGV || false;
156 static final boolean DEBUG_OOM_ADJ = localLOGV || false;
157 static final boolean DEBUG_TRANSITION = localLOGV || false;
158 static final boolean DEBUG_BROADCAST = localLOGV || false;
Dianne Hackborn82f3f002009-06-16 18:49:05 -0700159 static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800160 static final boolean DEBUG_SERVICE = localLOGV || false;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700161 static final boolean DEBUG_SERVICE_EXECUTING = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800162 static final boolean DEBUG_VISBILITY = localLOGV || false;
163 static final boolean DEBUG_PROCESSES = localLOGV || false;
Dianne Hackborna1e989b2009-09-01 19:54:29 -0700164 static final boolean DEBUG_PROVIDER = localLOGV || false;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800165 static final boolean DEBUG_URI_PERMISSION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800166 static final boolean DEBUG_USER_LEAVING = localLOGV || false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700167 static final boolean DEBUG_RESULTS = localLOGV || false;
Dianne Hackborn98cfebc2011-10-18 13:17:33 -0700168 static final boolean DEBUG_BACKUP = localLOGV || false;
Dianne Hackborndc6b6352009-09-30 14:20:09 -0700169 static final boolean DEBUG_CONFIGURATION = localLOGV || false;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700170 static final boolean DEBUG_POWER = localLOGV || false;
171 static final boolean DEBUG_POWER_QUICK = DEBUG_POWER || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800172 static final boolean VALIDATE_TOKENS = false;
173 static final boolean SHOW_ACTIVITY_START_TIME = true;
174
175 // Control over CPU and battery monitoring.
176 static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes.
177 static final boolean MONITOR_CPU_USAGE = true;
178 static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds.
179 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample.
180 static final boolean MONITOR_THREAD_CPU_USAGE = false;
181
Dianne Hackborn1655be42009-05-08 14:29:01 -0700182 // The flags that are set for all calls we make to the package manager.
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700183 static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
Dianne Hackborn1655be42009-05-08 14:29:01 -0700184
Dianne Hackbornf02e57b2011-03-01 22:21:04 -0800185 private static final String SYSTEM_DEBUGGABLE = "ro.debuggable";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800186
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800187 // Maximum number of recent tasks that we can remember.
188 static final int MAX_RECENT_TASKS = 20;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700189
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700190 // Amount of time after a call to stopAppSwitches() during which we will
191 // prevent further untrusted switches from happening.
192 static final long APP_SWITCH_DELAY_TIME = 5*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800193
194 // How long we wait for a launched process to attach to the activity manager
195 // before we decide it's never going to come up for real.
196 static final int PROC_START_TIMEOUT = 10*1000;
197
Jeff Brown3f9dd282011-07-08 20:02:19 -0700198 // How long we wait for a launched process to attach to the activity manager
199 // before we decide it's never going to come up for real, when the process was
200 // started with a wrapper for instrumentation (such as Valgrind) because it
201 // could take much longer than usual.
202 static final int PROC_START_TIMEOUT_WITH_WRAPPER = 300*1000;
203
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800204 // How long to wait after going idle before forcing apps to GC.
205 static final int GC_TIMEOUT = 5*1000;
206
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700207 // The minimum amount of time between successive GC requests for a process.
208 static final int GC_MIN_INTERVAL = 60*1000;
209
Dianne Hackborn287952c2010-09-22 22:34:31 -0700210 // The rate at which we check for apps using excessive power -- 15 mins.
211 static final int POWER_CHECK_DELAY = (DEBUG_POWER_QUICK ? 2 : 15) * 60*1000;
212
213 // The minimum sample duration we will allow before deciding we have
214 // enough data on wake locks to start killing things.
215 static final int WAKE_LOCK_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
216
217 // The minimum sample duration we will allow before deciding we have
218 // enough data on CPU usage to start killing things.
219 static final int CPU_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700220
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800221 // How long we allow a receiver to run before giving up on it.
222 static final int BROADCAST_TIMEOUT = 10*1000;
223
224 // How long we wait for a service to finish executing.
225 static final int SERVICE_TIMEOUT = 20*1000;
226
227 // How long a service needs to be running until restarting its process
228 // is no longer considered to be a relaunch of the service.
229 static final int SERVICE_RESTART_DURATION = 5*1000;
230
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700231 // How long a service needs to be running until it will start back at
232 // SERVICE_RESTART_DURATION after being killed.
233 static final int SERVICE_RESET_RUN_DURATION = 60*1000;
234
235 // Multiplying factor to increase restart duration time by, for each time
236 // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
237 static final int SERVICE_RESTART_DURATION_FACTOR = 4;
238
239 // The minimum amount of time between restarting services that we allow.
240 // That is, when multiple services are restarting, we won't allow each
241 // to restart less than this amount of time from the last one.
242 static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
243
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800244 // Maximum amount of time for there to be no activity on a service before
245 // we consider it non-essential and allow its process to go on the
246 // LRU background list.
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700247 static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800248
249 // How long we wait until we timeout on key dispatching.
250 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
251
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800252 // How long we wait until we timeout on key dispatching during instrumentation.
253 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
254
Dan Egnor42471dd2010-01-07 17:25:22 -0800255 static final int MY_PID = Process.myPid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800256
257 static final String[] EMPTY_STRING_ARRAY = new String[0];
258
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700259 public ActivityStack mMainStack;
260
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800261 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700262 * Description of a request to start a new activity, which has been held
263 * due to app switches being disabled.
264 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700265 static class PendingActivityLaunch {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700266 ActivityRecord r;
267 ActivityRecord sourceRecord;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700268 Uri[] grantedUriPermissions;
269 int grantedMode;
270 boolean onlyIfNeeded;
271 }
272
273 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
274 = new ArrayList<PendingActivityLaunch>();
275
276 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800277 * List of all active broadcasts that are to be executed immediately
278 * (without waiting for another broadcast to finish). Currently this only
279 * contains broadcasts to registered receivers, to avoid spinning up
280 * a bunch of processes to execute IntentReceiver components.
281 */
282 final ArrayList<BroadcastRecord> mParallelBroadcasts
283 = new ArrayList<BroadcastRecord>();
284
285 /**
286 * List of all active broadcasts that are to be executed one at a time.
287 * The object at the top of the list is the currently activity broadcasts;
288 * those after it are waiting for the top to finish..
289 */
290 final ArrayList<BroadcastRecord> mOrderedBroadcasts
291 = new ArrayList<BroadcastRecord>();
292
293 /**
Dianne Hackborn12527f92009-11-11 17:39:50 -0800294 * Historical data of past broadcasts, for debugging.
295 */
296 static final int MAX_BROADCAST_HISTORY = 100;
297 final BroadcastRecord[] mBroadcastHistory
298 = new BroadcastRecord[MAX_BROADCAST_HISTORY];
299
300 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800301 * Set when we current have a BROADCAST_INTENT_MSG in flight.
302 */
303 boolean mBroadcastsScheduled = false;
304
305 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800306 * Activity we have told the window manager to have key focus.
307 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700308 ActivityRecord mFocusedActivity = null;
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700309 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800310 * List of intents that were used to start the most recent tasks.
311 */
Dianne Hackborn0c5001d2011-04-12 18:16:08 -0700312 final ArrayList<TaskRecord> mRecentTasks = new ArrayList<TaskRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800313
314 /**
Dianne Hackborn7d608422011-08-07 16:24:18 -0700315 * Process management.
316 */
317 final ProcessList mProcessList = new ProcessList();
318
319 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800320 * All of the applications we currently have running organized by name.
321 * The keys are strings of the application package name (as
322 * returned by the package manager), and the keys are ApplicationRecord
323 * objects.
324 */
Dianne Hackborn0c5001d2011-04-12 18:16:08 -0700325 final ProcessMap<ProcessRecord> mProcessNames = new ProcessMap<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800326
327 /**
Dianne Hackborn860755f2010-06-03 18:47:52 -0700328 * The currently running heavy-weight process, if any.
329 */
330 ProcessRecord mHeavyWeightProcess = null;
331
332 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800333 * The last time that various processes have crashed.
334 */
335 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
336
337 /**
338 * Set of applications that we consider to be bad, and will reject
339 * incoming broadcasts from (which the user has no control over).
340 * Processes are added to this set when they have crashed twice within
341 * a minimum amount of time; they are removed from it when they are
342 * later restarted (hopefully due to some user action). The value is the
343 * time it was added to the list.
344 */
345 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
346
347 /**
348 * All of the processes we currently have running organized by pid.
349 * The keys are the pid running the application.
350 *
351 * <p>NOTE: This object is protected by its own lock, NOT the global
352 * activity manager lock!
353 */
Dianne Hackborn0c5001d2011-04-12 18:16:08 -0700354 final SparseArray<ProcessRecord> mPidsSelfLocked = new SparseArray<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800355
356 /**
357 * All of the processes that have been forced to be foreground. The key
358 * is the pid of the caller who requested it (we hold a death
359 * link on it).
360 */
361 abstract class ForegroundToken implements IBinder.DeathRecipient {
362 int pid;
363 IBinder token;
364 }
365 final SparseArray<ForegroundToken> mForegroundProcesses
366 = new SparseArray<ForegroundToken>();
367
368 /**
369 * List of records for processes that someone had tried to start before the
370 * system was ready. We don't start them at that point, but ensure they
371 * are started by the time booting is complete.
372 */
373 final ArrayList<ProcessRecord> mProcessesOnHold
374 = new ArrayList<ProcessRecord>();
375
376 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800377 * List of persistent applications that are in the process
378 * of being started.
379 */
380 final ArrayList<ProcessRecord> mPersistentStartingProcesses
381 = new ArrayList<ProcessRecord>();
382
383 /**
384 * Processes that are being forcibly torn down.
385 */
386 final ArrayList<ProcessRecord> mRemovedProcesses
387 = new ArrayList<ProcessRecord>();
388
389 /**
390 * List of running applications, sorted by recent usage.
391 * The first entry in the list is the least recently used.
392 * It contains ApplicationRecord objects. This list does NOT include
393 * any persistent application records (since we never want to exit them).
394 */
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800395 final ArrayList<ProcessRecord> mLruProcesses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800396 = new ArrayList<ProcessRecord>();
397
398 /**
399 * List of processes that should gc as soon as things are idle.
400 */
401 final ArrayList<ProcessRecord> mProcessesToGc
402 = new ArrayList<ProcessRecord>();
403
404 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -0800405 * This is the process holding what we currently consider to be
406 * the "home" activity.
407 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700408 ProcessRecord mHomeProcess;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800409
410 /**
Dianne Hackborne2515ee2011-04-27 18:52:56 -0400411 * Packages that the user has asked to have run in screen size
412 * compatibility mode instead of filling the screen.
413 */
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -0700414 final CompatModePackages mCompatModePackages;
Dianne Hackborne2515ee2011-04-27 18:52:56 -0400415
416 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800417 * Set of PendingResultRecord objects that are currently active.
418 */
419 final HashSet mPendingResultRecords = new HashSet();
420
421 /**
422 * Set of IntentSenderRecord objects that are currently active.
423 */
424 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
425 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
426
427 /**
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -0800428 * Fingerprints (hashCode()) of stack traces that we've
Brad Fitzpatrick143666f2010-06-14 12:40:21 -0700429 * already logged DropBox entries for. Guarded by itself. If
430 * something (rogue user app) forces this over
431 * MAX_DUP_SUPPRESSED_STACKS entries, the contents are cleared.
432 */
433 private final HashSet<Integer> mAlreadyLoggedViolatedStacks = new HashSet<Integer>();
434 private static final int MAX_DUP_SUPPRESSED_STACKS = 5000;
435
436 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -0700437 * Strict Mode background batched logging state.
438 *
439 * The string buffer is guarded by itself, and its lock is also
440 * used to determine if another batched write is already
441 * in-flight.
442 */
443 private final StringBuilder mStrictModeBuffer = new StringBuilder();
444
445 /**
Jeff Brown4d94a762010-09-23 11:33:28 -0700446 * True if we have a pending unexpired BROADCAST_TIMEOUT_MSG posted to our handler.
447 */
448 private boolean mPendingBroadcastTimeoutMessage;
449
450 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800451 * Intent broadcast that we have tried to start, but are
452 * waiting for its application's process to be created. We only
453 * need one (instead of a list) because we always process broadcasts
454 * one at a time, so no others can be started while waiting for this
455 * one.
456 */
457 BroadcastRecord mPendingBroadcast = null;
458
459 /**
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700460 * The receiver index that is pending, to restart the broadcast if needed.
461 */
462 int mPendingBroadcastRecvIndex;
463
464 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800465 * Keeps track of all IIntentReceivers that have been registered for
466 * broadcasts. Hash keys are the receiver IBinder, hash value is
467 * a ReceiverList.
468 */
469 final HashMap mRegisteredReceivers = new HashMap();
470
471 /**
472 * Resolver for broadcast intents to registered receivers.
473 * Holds BroadcastFilter (subclass of IntentFilter).
474 */
475 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
476 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
477 @Override
478 protected boolean allowFilterResult(
479 BroadcastFilter filter, List<BroadcastFilter> dest) {
480 IBinder target = filter.receiverList.receiver.asBinder();
481 for (int i=dest.size()-1; i>=0; i--) {
482 if (dest.get(i).receiverList.receiver.asBinder() == target) {
483 return false;
484 }
485 }
486 return true;
487 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -0700488
489 @Override
490 protected String packageForFilter(BroadcastFilter filter) {
491 return filter.packageName;
492 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800493 };
494
495 /**
496 * State of all active sticky broadcasts. Keys are the action of the
497 * sticky Intent, values are an ArrayList of all broadcasted intents with
498 * that action (which should usually be one).
499 */
500 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
501 new HashMap<String, ArrayList<Intent>>();
502
503 /**
504 * All currently running services.
505 */
506 final HashMap<ComponentName, ServiceRecord> mServices =
507 new HashMap<ComponentName, ServiceRecord>();
508
509 /**
510 * All currently running services indexed by the Intent used to start them.
511 */
512 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
513 new HashMap<Intent.FilterComparison, ServiceRecord>();
514
515 /**
516 * All currently bound service connections. Keys are the IBinder of
517 * the client's IServiceConnection.
518 */
Dianne Hackborn43d9ac82010-08-25 15:06:25 -0700519 final HashMap<IBinder, ArrayList<ConnectionRecord>> mServiceConnections
520 = new HashMap<IBinder, ArrayList<ConnectionRecord>>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800521
522 /**
523 * List of services that we have been asked to start,
524 * but haven't yet been able to. It is used to hold start requests
525 * while waiting for their corresponding application thread to get
526 * going.
527 */
528 final ArrayList<ServiceRecord> mPendingServices
529 = new ArrayList<ServiceRecord>();
530
531 /**
532 * List of services that are scheduled to restart following a crash.
533 */
534 final ArrayList<ServiceRecord> mRestartingServices
535 = new ArrayList<ServiceRecord>();
536
537 /**
538 * List of services that are in the process of being stopped.
539 */
540 final ArrayList<ServiceRecord> mStoppingServices
541 = new ArrayList<ServiceRecord>();
542
543 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700544 * Backup/restore process management
545 */
546 String mBackupAppName = null;
547 BackupRecord mBackupTarget = null;
548
549 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800550 * List of PendingThumbnailsRecord objects of clients who are still
551 * waiting to receive all of the thumbnails for a task.
552 */
553 final ArrayList mPendingThumbnails = new ArrayList();
554
555 /**
556 * List of HistoryRecord objects that have been finished and must
557 * still report back to a pending thumbnail receiver.
558 */
559 final ArrayList mCancelledThumbnails = new ArrayList();
560
561 /**
562 * All of the currently running global content providers. Keys are a
563 * string containing the provider name and values are a
564 * ContentProviderRecord object containing the data about it. Note
565 * that a single provider may be published under multiple names, so
566 * there may be multiple entries here for a single one in mProvidersByClass.
567 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700568 final HashMap<String, ContentProviderRecord> mProvidersByName
569 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800570
571 /**
572 * All of the currently running global content providers. Keys are a
573 * string containing the provider's implementation class and values are a
574 * ContentProviderRecord object containing the data about it.
575 */
Dianne Hackborn1c9b2602011-08-19 14:08:43 -0700576 final HashMap<ComponentName, ContentProviderRecord> mProvidersByClass
577 = new HashMap<ComponentName, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800578
579 /**
580 * List of content providers who have clients waiting for them. The
581 * application is currently being launched and the provider will be
582 * removed from this list once it is published.
583 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700584 final ArrayList<ContentProviderRecord> mLaunchingProviders
585 = new ArrayList<ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800586
587 /**
588 * Global set of specific Uri permissions that have been granted.
589 */
590 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
591 = new SparseArray<HashMap<Uri, UriPermission>>();
592
Svetoslav Ganov54d068e2011-03-02 12:58:40 -0800593 CoreSettingsObserver mCoreSettingsObserver;
594
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800595 /**
596 * Thread-local storage used to carry caller permissions over through
597 * indirect content-provider access.
598 * @see #ActivityManagerService.openContentUri()
599 */
600 private class Identity {
601 public int pid;
602 public int uid;
603
604 Identity(int _pid, int _uid) {
605 pid = _pid;
606 uid = _uid;
607 }
608 }
609 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
610
611 /**
612 * All information we have collected about the runtime performance of
613 * any user id that can impact battery performance.
614 */
615 final BatteryStatsService mBatteryStatsService;
616
617 /**
618 * information about component usage
619 */
620 final UsageStatsService mUsageStatsService;
621
622 /**
623 * Current configuration information. HistoryRecord objects are given
624 * a reference to this object to indicate which configuration they are
625 * currently running in, so this object must be kept immutable.
626 */
627 Configuration mConfiguration = new Configuration();
628
629 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800630 * Current sequencing integer of the configuration, for skipping old
631 * configurations.
632 */
633 int mConfigurationSeq = 0;
634
635 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700636 * Hardware-reported OpenGLES version.
637 */
638 final int GL_ES_VERSION;
639
640 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800641 * List of initialization arguments to pass to all processes when binding applications to them.
642 * For example, references to the commonly used services.
643 */
644 HashMap<String, IBinder> mAppBindArgs;
645
646 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700647 * Temporary to avoid allocations. Protected by main lock.
648 */
649 final StringBuilder mStringBuilder = new StringBuilder(256);
650
651 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800652 * Used to control how we initialize the service.
653 */
654 boolean mStartRunning = false;
655 ComponentName mTopComponent;
656 String mTopAction;
657 String mTopData;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700658 boolean mProcessesReady = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800659 boolean mSystemReady = false;
660 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700661 boolean mWaitingUpdate = false;
662 boolean mDidUpdate = false;
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700663 boolean mOnBattery = false;
Dianne Hackborn0dad3642010-09-09 21:25:35 -0700664 boolean mLaunchWarningShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800665
666 Context mContext;
667
668 int mFactoryTest;
669
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700670 boolean mCheckedForSetup;
671
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800672 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700673 * The time at which we will allow normal application switches again,
674 * after a call to {@link #stopAppSwitches()}.
675 */
676 long mAppSwitchesAllowedTime;
677
678 /**
679 * This is set to true after the first switch after mAppSwitchesAllowedTime
680 * is set; any switches after that will clear the time.
681 */
682 boolean mDidAppSwitch;
683
684 /**
Dianne Hackborn287952c2010-09-22 22:34:31 -0700685 * Last time (in realtime) at which we checked for power usage.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700686 */
Dianne Hackborn287952c2010-09-22 22:34:31 -0700687 long mLastPowerCheckRealtime;
688
689 /**
690 * Last time (in uptime) at which we checked for power usage.
691 */
692 long mLastPowerCheckUptime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700693
694 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800695 * Set while we are wanting to sleep, to prevent any
696 * activities from being started/resumed.
697 */
698 boolean mSleeping = false;
699
700 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700701 * Set if we are shutting down the system, similar to sleeping.
702 */
703 boolean mShuttingDown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800704
705 /**
706 * Task identifier that activities are currently being started
707 * in. Incremented each time a new task is created.
708 * todo: Replace this with a TokenSpace class that generates non-repeating
709 * integers that won't wrap.
710 */
711 int mCurTask = 1;
712
713 /**
714 * Current sequence id for oom_adj computation traversal.
715 */
716 int mAdjSeq = 0;
717
718 /**
Dianne Hackborn906497c2010-05-10 15:57:38 -0700719 * Current sequence id for process LRU updating.
720 */
721 int mLruSeq = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800722
723 /**
724 * System monitoring: number of processes that died since the last
725 * N procs were started.
726 */
727 int[] mProcDeaths = new int[20];
728
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700729 /**
730 * This is set if we had to do a delayed dexopt of an app before launching
731 * it, to increasing the ANR timeouts in that case.
732 */
733 boolean mDidDexOpt;
734
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800735 String mDebugApp = null;
736 boolean mWaitForDebugger = false;
737 boolean mDebugTransient = false;
738 String mOrigDebugApp = null;
739 boolean mOrigWaitForDebugger = false;
740 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700741 IActivityController mController = null;
Dianne Hackborn62f20ec2011-08-15 17:40:28 -0700742 String mProfileApp = null;
743 ProcessRecord mProfileProc = null;
744 String mProfileFile;
745 ParcelFileDescriptor mProfileFd;
746 int mProfileType = 0;
747 boolean mAutoStopProfiler = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800748
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700749 final RemoteCallbackList<IActivityWatcher> mWatchers
750 = new RemoteCallbackList<IActivityWatcher>();
Jeff Sharkeya4620792011-05-20 15:29:23 -0700751
752 final RemoteCallbackList<IProcessObserver> mProcessObservers
753 = new RemoteCallbackList<IProcessObserver>();
754
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800755 /**
756 * Callback of last caller to {@link #requestPss}.
757 */
758 Runnable mRequestPssCallback;
759
760 /**
761 * Remaining processes for which we are waiting results from the last
762 * call to {@link #requestPss}.
763 */
764 final ArrayList<ProcessRecord> mRequestPssList
765 = new ArrayList<ProcessRecord>();
766
767 /**
768 * Runtime statistics collection thread. This object's lock is used to
769 * protect all related state.
770 */
771 final Thread mProcessStatsThread;
772
773 /**
774 * Used to collect process stats when showing not responding dialog.
775 * Protected by mProcessStatsThread.
776 */
777 final ProcessStats mProcessStats = new ProcessStats(
778 MONITOR_THREAD_CPU_USAGE);
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700779 final AtomicLong mLastCpuTime = new AtomicLong(0);
780 final AtomicBoolean mProcessStatsMutexFree = new AtomicBoolean(true);
781
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800782 long mLastWriteTime = 0;
783
784 /**
785 * Set to true after the system has finished booting.
786 */
787 boolean mBooted = false;
788
Dianne Hackborn7d608422011-08-07 16:24:18 -0700789 int mProcessLimit = ProcessList.MAX_HIDDEN_APPS;
Dianne Hackbornce86ba82011-07-13 19:33:41 -0700790 int mProcessLimitOverride = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800791
792 WindowManagerService mWindowManager;
793
794 static ActivityManagerService mSelf;
795 static ActivityThread mSystemThread;
796
797 private final class AppDeathRecipient implements IBinder.DeathRecipient {
798 final ProcessRecord mApp;
799 final int mPid;
800 final IApplicationThread mAppThread;
801
802 AppDeathRecipient(ProcessRecord app, int pid,
803 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800804 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800805 TAG, "New death recipient " + this
806 + " for thread " + thread.asBinder());
807 mApp = app;
808 mPid = pid;
809 mAppThread = thread;
810 }
811
812 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800813 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800814 TAG, "Death received in " + this
815 + " for thread " + mAppThread.asBinder());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800816 synchronized(ActivityManagerService.this) {
817 appDiedLocked(mApp, mPid, mAppThread);
818 }
819 }
820 }
821
822 static final int SHOW_ERROR_MSG = 1;
823 static final int SHOW_NOT_RESPONDING_MSG = 2;
824 static final int SHOW_FACTORY_ERROR_MSG = 3;
825 static final int UPDATE_CONFIGURATION_MSG = 4;
826 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
827 static final int WAIT_FOR_DEBUGGER_MSG = 6;
828 static final int BROADCAST_INTENT_MSG = 7;
829 static final int BROADCAST_TIMEOUT_MSG = 8;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800830 static final int SERVICE_TIMEOUT_MSG = 12;
831 static final int UPDATE_TIME_ZONE = 13;
832 static final int SHOW_UID_ERROR_MSG = 14;
833 static final int IM_FEELING_LUCKY_MSG = 15;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800834 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700835 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -0700836 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800837 static final int FINALIZE_PENDING_INTENT_MSG = 23;
Dianne Hackborn860755f2010-06-03 18:47:52 -0700838 static final int POST_HEAVY_NOTIFICATION_MSG = 24;
839 static final int CANCEL_HEAVY_NOTIFICATION_MSG = 25;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700840 static final int SHOW_STRICT_MODE_VIOLATION_MSG = 26;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700841 static final int CHECK_EXCESSIVE_WAKE_LOCKS_MSG = 27;
Robert Greenwalt03595d02010-11-02 14:08:23 -0700842 static final int CLEAR_DNS_CACHE = 28;
Robert Greenwalt434203a2010-10-11 16:00:27 -0700843 static final int UPDATE_HTTP_PROXY = 29;
Dianne Hackborn36cd41f2011-05-25 21:00:46 -0700844 static final int SHOW_COMPAT_MODE_DIALOG_MSG = 30;
Dianne Hackborn36f80f32011-05-31 18:26:45 -0700845 static final int DISPATCH_FOREGROUND_ACTIVITIES_CHANGED = 31;
846 static final int DISPATCH_PROCESS_DIED = 32;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800847
848 AlertDialog mUidAlert;
Dianne Hackborn36cd41f2011-05-25 21:00:46 -0700849 CompatModeDialog mCompatModeDialog;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800850
851 final Handler mHandler = new Handler() {
852 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800853 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800854 //}
855
856 public void handleMessage(Message msg) {
857 switch (msg.what) {
858 case SHOW_ERROR_MSG: {
859 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800860 synchronized (ActivityManagerService.this) {
861 ProcessRecord proc = (ProcessRecord)data.get("app");
862 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800863 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800864 return;
865 }
866 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -0700867 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -0800868 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800869 d.show();
870 proc.crashDialog = d;
871 } else {
872 // The device is asleep, so just pretend that the user
873 // saw a crash dialog and hit "force quit".
874 res.set(0);
875 }
876 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700877
878 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800879 } break;
880 case SHOW_NOT_RESPONDING_MSG: {
881 synchronized (ActivityManagerService.this) {
882 HashMap data = (HashMap) msg.obj;
883 ProcessRecord proc = (ProcessRecord)data.get("app");
884 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800885 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800886 return;
887 }
The Android Open Source Project4df24232009-03-05 14:34:35 -0800888
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700889 Intent intent = new Intent("android.intent.action.ANR");
890 if (!mProcessesReady) {
891 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
892 }
893 broadcastIntentLocked(null, null, intent,
The Android Open Source Project4df24232009-03-05 14:34:35 -0800894 null, null, 0, null, null, null,
895 false, false, MY_PID, Process.SYSTEM_UID);
896
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800897 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700898 mContext, proc, (ActivityRecord)data.get("activity"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800899 d.show();
900 proc.anrDialog = d;
901 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700902
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700903 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800904 } break;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700905 case SHOW_STRICT_MODE_VIOLATION_MSG: {
906 HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
907 synchronized (ActivityManagerService.this) {
908 ProcessRecord proc = (ProcessRecord) data.get("app");
909 if (proc == null) {
910 Slog.e(TAG, "App not found when showing strict mode dialog.");
911 break;
912 }
913 if (proc.crashDialog != null) {
914 Slog.e(TAG, "App already has strict mode dialog: " + proc);
915 return;
916 }
917 AppErrorResult res = (AppErrorResult) data.get("result");
918 if (!mSleeping && !mShuttingDown) {
919 Dialog d = new StrictModeViolationDialog(mContext, res, proc);
920 d.show();
921 proc.crashDialog = d;
922 } else {
923 // The device is asleep, so just pretend that the user
924 // saw a crash dialog and hit "force quit".
925 res.set(0);
926 }
927 }
928 ensureBootCompleted();
929 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800930 case SHOW_FACTORY_ERROR_MSG: {
931 Dialog d = new FactoryErrorDialog(
932 mContext, msg.getData().getCharSequence("msg"));
933 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700934 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800935 } break;
936 case UPDATE_CONFIGURATION_MSG: {
937 final ContentResolver resolver = mContext.getContentResolver();
938 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
939 } break;
940 case GC_BACKGROUND_PROCESSES_MSG: {
941 synchronized (ActivityManagerService.this) {
942 performAppGcsIfAppropriateLocked();
943 }
944 } break;
945 case WAIT_FOR_DEBUGGER_MSG: {
946 synchronized (ActivityManagerService.this) {
947 ProcessRecord app = (ProcessRecord)msg.obj;
948 if (msg.arg1 != 0) {
949 if (!app.waitedForDebugger) {
950 Dialog d = new AppWaitingForDebuggerDialog(
951 ActivityManagerService.this,
952 mContext, app);
953 app.waitDialog = d;
954 app.waitedForDebugger = true;
955 d.show();
956 }
957 } else {
958 if (app.waitDialog != null) {
959 app.waitDialog.dismiss();
960 app.waitDialog = null;
961 }
962 }
963 }
964 } break;
965 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800966 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800967 TAG, "Received BROADCAST_INTENT_MSG");
968 processNextBroadcast(true);
969 } break;
970 case BROADCAST_TIMEOUT_MSG: {
Jeff Brown4d94a762010-09-23 11:33:28 -0700971 synchronized (ActivityManagerService.this) {
972 broadcastTimeoutLocked(true);
Jeff Hamiltonacf84742010-05-25 22:10:18 -0500973 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800974 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800975 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700976 if (mDidDexOpt) {
977 mDidDexOpt = false;
978 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
979 nmsg.obj = msg.obj;
980 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
981 return;
982 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800983 serviceTimeout((ProcessRecord)msg.obj);
984 } break;
985 case UPDATE_TIME_ZONE: {
986 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800987 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
988 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800989 if (r.thread != null) {
990 try {
991 r.thread.updateTimeZone();
992 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800993 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800994 }
995 }
996 }
997 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700998 } break;
Robert Greenwalt03595d02010-11-02 14:08:23 -0700999 case CLEAR_DNS_CACHE: {
1000 synchronized (ActivityManagerService.this) {
1001 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1002 ProcessRecord r = mLruProcesses.get(i);
1003 if (r.thread != null) {
1004 try {
1005 r.thread.clearDnsCache();
1006 } catch (RemoteException ex) {
1007 Slog.w(TAG, "Failed to clear dns cache for: " + r.info.processName);
1008 }
1009 }
1010 }
1011 }
1012 } break;
Robert Greenwalt434203a2010-10-11 16:00:27 -07001013 case UPDATE_HTTP_PROXY: {
1014 ProxyProperties proxy = (ProxyProperties)msg.obj;
1015 String host = "";
1016 String port = "";
1017 String exclList = "";
1018 if (proxy != null) {
1019 host = proxy.getHost();
1020 port = Integer.toString(proxy.getPort());
1021 exclList = proxy.getExclusionList();
1022 }
1023 synchronized (ActivityManagerService.this) {
1024 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1025 ProcessRecord r = mLruProcesses.get(i);
1026 if (r.thread != null) {
1027 try {
1028 r.thread.setHttpProxy(host, port, exclList);
1029 } catch (RemoteException ex) {
1030 Slog.w(TAG, "Failed to update http proxy for: " +
1031 r.info.processName);
1032 }
1033 }
1034 }
1035 }
1036 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001037 case SHOW_UID_ERROR_MSG: {
1038 // XXX This is a temporary dialog, no need to localize.
1039 AlertDialog d = new BaseErrorDialog(mContext);
1040 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1041 d.setCancelable(false);
1042 d.setTitle("System UIDs Inconsistent");
1043 d.setMessage("UIDs on the system are inconsistent, you need to wipe your data partition or your device will be unstable.");
Christian Mehlmauer7664e202010-07-20 08:46:17 +02001044 d.setButton(DialogInterface.BUTTON_POSITIVE, "I'm Feeling Lucky",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001045 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1046 mUidAlert = d;
1047 d.show();
1048 } break;
1049 case IM_FEELING_LUCKY_MSG: {
1050 if (mUidAlert != null) {
1051 mUidAlert.dismiss();
1052 mUidAlert = null;
1053 }
1054 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001055 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001056 if (mDidDexOpt) {
1057 mDidDexOpt = false;
1058 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1059 nmsg.obj = msg.obj;
1060 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1061 return;
1062 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001063 ProcessRecord app = (ProcessRecord)msg.obj;
1064 synchronized (ActivityManagerService.this) {
1065 processStartTimedOutLocked(app);
1066 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001067 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001068 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1069 synchronized (ActivityManagerService.this) {
1070 doPendingActivityLaunchesLocked(true);
1071 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001072 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001073 case KILL_APPLICATION_MSG: {
1074 synchronized (ActivityManagerService.this) {
1075 int uid = msg.arg1;
1076 boolean restart = (msg.arg2 == 1);
1077 String pkg = (String) msg.obj;
Christopher Tate3dacd842011-08-19 14:56:15 -07001078 forceStopPackageLocked(pkg, uid, restart, false, true, false);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001079 }
1080 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001081 case FINALIZE_PENDING_INTENT_MSG: {
1082 ((PendingIntentRecord)msg.obj).completeFinalize();
1083 } break;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001084 case POST_HEAVY_NOTIFICATION_MSG: {
1085 INotificationManager inm = NotificationManager.getService();
1086 if (inm == null) {
1087 return;
1088 }
1089
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001090 ActivityRecord root = (ActivityRecord)msg.obj;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001091 ProcessRecord process = root.app;
1092 if (process == null) {
1093 return;
1094 }
1095
1096 try {
1097 Context context = mContext.createPackageContext(process.info.packageName, 0);
1098 String text = mContext.getString(R.string.heavy_weight_notification,
1099 context.getApplicationInfo().loadLabel(context.getPackageManager()));
1100 Notification notification = new Notification();
1101 notification.icon = com.android.internal.R.drawable.stat_sys_adb; //context.getApplicationInfo().icon;
1102 notification.when = 0;
1103 notification.flags = Notification.FLAG_ONGOING_EVENT;
1104 notification.tickerText = text;
1105 notification.defaults = 0; // please be quiet
1106 notification.sound = null;
1107 notification.vibrate = null;
1108 notification.setLatestEventInfo(context, text,
1109 mContext.getText(R.string.heavy_weight_notification_detail),
1110 PendingIntent.getActivity(mContext, 0, root.intent,
1111 PendingIntent.FLAG_CANCEL_CURRENT));
1112
1113 try {
1114 int[] outId = new int[1];
1115 inm.enqueueNotification("android", R.string.heavy_weight_notification,
1116 notification, outId);
1117 } catch (RuntimeException e) {
1118 Slog.w(ActivityManagerService.TAG,
1119 "Error showing notification for heavy-weight app", e);
1120 } catch (RemoteException e) {
1121 }
1122 } catch (NameNotFoundException e) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07001123 Slog.w(TAG, "Unable to create context for heavy notification", e);
Dianne Hackborn860755f2010-06-03 18:47:52 -07001124 }
1125 } break;
1126 case CANCEL_HEAVY_NOTIFICATION_MSG: {
1127 INotificationManager inm = NotificationManager.getService();
1128 if (inm == null) {
1129 return;
1130 }
1131 try {
1132 inm.cancelNotification("android",
1133 R.string.heavy_weight_notification);
1134 } catch (RuntimeException e) {
1135 Slog.w(ActivityManagerService.TAG,
1136 "Error canceling notification for service", e);
1137 } catch (RemoteException e) {
1138 }
1139 } break;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001140 case CHECK_EXCESSIVE_WAKE_LOCKS_MSG: {
1141 synchronized (ActivityManagerService.this) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001142 checkExcessivePowerUsageLocked(true);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -07001143 removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001144 Message nmsg = obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
1145 sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001146 }
1147 } break;
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07001148 case SHOW_COMPAT_MODE_DIALOG_MSG: {
1149 synchronized (ActivityManagerService.this) {
1150 ActivityRecord ar = (ActivityRecord)msg.obj;
1151 if (mCompatModeDialog != null) {
1152 if (mCompatModeDialog.mAppInfo.packageName.equals(
1153 ar.info.applicationInfo.packageName)) {
1154 return;
1155 }
1156 mCompatModeDialog.dismiss();
1157 mCompatModeDialog = null;
1158 }
Dianne Hackborn29478262011-06-07 15:44:22 -07001159 if (ar != null && false) {
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07001160 if (mCompatModePackages.getPackageAskCompatModeLocked(
1161 ar.packageName)) {
1162 int mode = mCompatModePackages.computeCompatModeLocked(
1163 ar.info.applicationInfo);
1164 if (mode == ActivityManager.COMPAT_MODE_DISABLED
1165 || mode == ActivityManager.COMPAT_MODE_ENABLED) {
1166 mCompatModeDialog = new CompatModeDialog(
1167 ActivityManagerService.this, mContext,
1168 ar.info.applicationInfo);
1169 mCompatModeDialog.show();
1170 }
1171 }
1172 }
1173 }
Dianne Hackborn36f80f32011-05-31 18:26:45 -07001174 break;
1175 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07001176 case DISPATCH_FOREGROUND_ACTIVITIES_CHANGED: {
Jeff Sharkey287bd832011-05-28 19:36:26 -07001177 final int pid = msg.arg1;
1178 final int uid = msg.arg2;
1179 final boolean foregroundActivities = (Boolean) msg.obj;
1180 dispatchForegroundActivitiesChanged(pid, uid, foregroundActivities);
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07001181 break;
1182 }
1183 case DISPATCH_PROCESS_DIED: {
Jeff Sharkey287bd832011-05-28 19:36:26 -07001184 final int pid = msg.arg1;
1185 final int uid = msg.arg2;
1186 dispatchProcessDied(pid, uid);
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07001187 break;
1188 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001189 }
1190 }
1191 };
1192
1193 public static void setSystemProcess() {
1194 try {
1195 ActivityManagerService m = mSelf;
1196
1197 ServiceManager.addService("activity", m);
1198 ServiceManager.addService("meminfo", new MemBinder(m));
Chet Haase9c1e23b2011-03-24 10:51:31 -07001199 ServiceManager.addService("gfxinfo", new GraphicsBinder(m));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001200 if (MONITOR_CPU_USAGE) {
1201 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1202 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001203 ServiceManager.addService("permission", new PermissionController(m));
1204
1205 ApplicationInfo info =
1206 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001207 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001208 mSystemThread.installSystemApplicationInfo(info);
1209
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001210 synchronized (mSelf) {
1211 ProcessRecord app = mSelf.newProcessRecordLocked(
1212 mSystemThread.getApplicationThread(), info,
1213 info.processName);
1214 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001215 app.pid = MY_PID;
Dianne Hackborn7d608422011-08-07 16:24:18 -07001216 app.maxAdj = ProcessList.SYSTEM_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001217 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1218 synchronized (mSelf.mPidsSelfLocked) {
1219 mSelf.mPidsSelfLocked.put(app.pid, app);
1220 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001221 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001222 }
1223 } catch (PackageManager.NameNotFoundException e) {
1224 throw new RuntimeException(
1225 "Unable to find android system package", e);
1226 }
1227 }
1228
1229 public void setWindowManager(WindowManagerService wm) {
1230 mWindowManager = wm;
1231 }
1232
1233 public static final Context main(int factoryTest) {
1234 AThread thr = new AThread();
1235 thr.start();
1236
1237 synchronized (thr) {
1238 while (thr.mService == null) {
1239 try {
1240 thr.wait();
1241 } catch (InterruptedException e) {
1242 }
1243 }
1244 }
1245
1246 ActivityManagerService m = thr.mService;
1247 mSelf = m;
1248 ActivityThread at = ActivityThread.systemMain();
1249 mSystemThread = at;
1250 Context context = at.getSystemContext();
Dianne Hackborn247fe742011-01-08 17:25:57 -08001251 context.setTheme(android.R.style.Theme_Holo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001252 m.mContext = context;
1253 m.mFactoryTest = factoryTest;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001254 m.mMainStack = new ActivityStack(m, context, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001255
1256 m.mBatteryStatsService.publish(context);
1257 m.mUsageStatsService.publish(context);
1258
1259 synchronized (thr) {
1260 thr.mReady = true;
1261 thr.notifyAll();
1262 }
1263
1264 m.startRunning(null, null, null, null);
1265
1266 return context;
1267 }
1268
1269 public static ActivityManagerService self() {
1270 return mSelf;
1271 }
1272
1273 static class AThread extends Thread {
1274 ActivityManagerService mService;
1275 boolean mReady = false;
1276
1277 public AThread() {
1278 super("ActivityManager");
1279 }
1280
1281 public void run() {
1282 Looper.prepare();
1283
1284 android.os.Process.setThreadPriority(
1285 android.os.Process.THREAD_PRIORITY_FOREGROUND);
Christopher Tate160edb32010-06-30 17:46:30 -07001286 android.os.Process.setCanSelfBackground(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001287
1288 ActivityManagerService m = new ActivityManagerService();
1289
1290 synchronized (this) {
1291 mService = m;
1292 notifyAll();
1293 }
1294
1295 synchronized (this) {
1296 while (!mReady) {
1297 try {
1298 wait();
1299 } catch (InterruptedException e) {
1300 }
1301 }
1302 }
1303
Brad Fitzpatrickec062f62010-11-03 09:56:54 -07001304 // For debug builds, log event loop stalls to dropbox for analysis.
1305 if (StrictMode.conditionallyEnableDebugLogging()) {
1306 Slog.i(TAG, "Enabled StrictMode logging for AThread's Looper");
1307 }
1308
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001309 Looper.loop();
1310 }
1311 }
1312
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001313 static class MemBinder extends Binder {
1314 ActivityManagerService mActivityManagerService;
1315 MemBinder(ActivityManagerService activityManagerService) {
1316 mActivityManagerService = activityManagerService;
1317 }
1318
1319 @Override
1320 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Kenny Root3abd75b2011-09-29 11:00:41 -07001321 if (mActivityManagerService.checkCallingPermission(android.Manifest.permission.DUMP)
1322 != PackageManager.PERMISSION_GRANTED) {
1323 pw.println("Permission Denial: can't dump meminfo from from pid="
1324 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
1325 + " without permission " + android.Manifest.permission.DUMP);
1326 return;
1327 }
1328
Dianne Hackborne17aeb32011-04-07 15:11:57 -07001329 mActivityManagerService.dumpApplicationMemoryUsage(fd, pw, " ", args);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001330 }
1331 }
1332
Chet Haase9c1e23b2011-03-24 10:51:31 -07001333 static class GraphicsBinder extends Binder {
1334 ActivityManagerService mActivityManagerService;
1335 GraphicsBinder(ActivityManagerService activityManagerService) {
1336 mActivityManagerService = activityManagerService;
1337 }
1338
1339 @Override
1340 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Kenny Root3abd75b2011-09-29 11:00:41 -07001341 if (mActivityManagerService.checkCallingPermission(android.Manifest.permission.DUMP)
1342 != PackageManager.PERMISSION_GRANTED) {
1343 pw.println("Permission Denial: can't dump gfxinfo from from pid="
1344 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
1345 + " without permission " + android.Manifest.permission.DUMP);
1346 return;
1347 }
1348
Dianne Hackborne17aeb32011-04-07 15:11:57 -07001349 mActivityManagerService.dumpGraphicsHardwareUsage(fd, pw, args);
Chet Haase9c1e23b2011-03-24 10:51:31 -07001350 }
1351 }
1352
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001353 static class CpuBinder extends Binder {
1354 ActivityManagerService mActivityManagerService;
1355 CpuBinder(ActivityManagerService activityManagerService) {
1356 mActivityManagerService = activityManagerService;
1357 }
1358
1359 @Override
1360 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Kenny Root3abd75b2011-09-29 11:00:41 -07001361 if (mActivityManagerService.checkCallingPermission(android.Manifest.permission.DUMP)
1362 != PackageManager.PERMISSION_GRANTED) {
1363 pw.println("Permission Denial: can't dump cpuinfo from from pid="
1364 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
1365 + " without permission " + android.Manifest.permission.DUMP);
1366 return;
1367 }
1368
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001369 synchronized (mActivityManagerService.mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07001370 pw.print(mActivityManagerService.mProcessStats.printCurrentLoad());
1371 pw.print(mActivityManagerService.mProcessStats.printCurrentState(
1372 SystemClock.uptimeMillis()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001373 }
1374 }
1375 }
1376
1377 private ActivityManagerService() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001378 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001379
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001380 File dataDir = Environment.getDataDirectory();
1381 File systemDir = new File(dataDir, "system");
1382 systemDir.mkdirs();
1383 mBatteryStatsService = new BatteryStatsService(new File(
1384 systemDir, "batterystats.bin").toString());
1385 mBatteryStatsService.getActiveStatistics().readLocked();
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001386 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
Dianne Hackborn287952c2010-09-22 22:34:31 -07001387 mOnBattery = DEBUG_POWER ? true
1388 : mBatteryStatsService.getActiveStatistics().getIsOnBattery();
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001389 mBatteryStatsService.getActiveStatistics().setCallback(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001390
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001391 mUsageStatsService = new UsageStatsService(new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001392 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001393
Jack Palevichb90d28c2009-07-22 15:35:24 -07001394 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1395 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1396
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001397 mConfiguration.setToDefaults();
1398 mConfiguration.locale = Locale.getDefault();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001399 mProcessStats.init();
1400
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07001401 mCompatModePackages = new CompatModePackages(this, systemDir);
1402
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001403 // Add ourself to the Watchdog monitors.
1404 Watchdog.getInstance().addMonitor(this);
1405
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001406 mProcessStatsThread = new Thread("ProcessStats") {
1407 public void run() {
1408 while (true) {
1409 try {
1410 try {
1411 synchronized(this) {
1412 final long now = SystemClock.uptimeMillis();
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001413 long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001414 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001415 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001416 // + ", write delay=" + nextWriteDelay);
1417 if (nextWriteDelay < nextCpuDelay) {
1418 nextCpuDelay = nextWriteDelay;
1419 }
1420 if (nextCpuDelay > 0) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001421 mProcessStatsMutexFree.set(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001422 this.wait(nextCpuDelay);
1423 }
1424 }
1425 } catch (InterruptedException e) {
1426 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001427 updateCpuStatsNow();
1428 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001429 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001430 }
1431 }
1432 }
1433 };
1434 mProcessStatsThread.start();
1435 }
1436
1437 @Override
1438 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1439 throws RemoteException {
1440 try {
1441 return super.onTransact(code, data, reply, flags);
1442 } catch (RuntimeException e) {
1443 // The activity manager only throws security exceptions, so let's
1444 // log all others.
1445 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001446 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001447 }
1448 throw e;
1449 }
1450 }
1451
1452 void updateCpuStats() {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001453 final long now = SystemClock.uptimeMillis();
1454 if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
1455 return;
1456 }
1457 if (mProcessStatsMutexFree.compareAndSet(true, false)) {
1458 synchronized (mProcessStatsThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001459 mProcessStatsThread.notify();
1460 }
1461 }
1462 }
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001463
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001464 void updateCpuStatsNow() {
1465 synchronized (mProcessStatsThread) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001466 mProcessStatsMutexFree.set(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001467 final long now = SystemClock.uptimeMillis();
1468 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001469
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001470 if (MONITOR_CPU_USAGE &&
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001471 mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
1472 mLastCpuTime.set(now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001473 haveNewCpuStats = true;
1474 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001475 //Slog.i(TAG, mProcessStats.printCurrentState());
1476 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001477 // + mProcessStats.getTotalCpuPercent() + "%");
1478
Joe Onorato8a9b2202010-02-26 18:56:32 -08001479 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001480 if ("true".equals(SystemProperties.get("events.cpu"))) {
1481 int user = mProcessStats.getLastUserTime();
1482 int system = mProcessStats.getLastSystemTime();
1483 int iowait = mProcessStats.getLastIoWaitTime();
1484 int irq = mProcessStats.getLastIrqTime();
1485 int softIrq = mProcessStats.getLastSoftIrqTime();
1486 int idle = mProcessStats.getLastIdleTime();
1487
1488 int total = user + system + iowait + irq + softIrq + idle;
1489 if (total == 0) total = 1;
1490
Doug Zongker2bec3d42009-12-04 12:52:44 -08001491 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001492 ((user+system+iowait+irq+softIrq) * 100) / total,
1493 (user * 100) / total,
1494 (system * 100) / total,
1495 (iowait * 100) / total,
1496 (irq * 100) / total,
1497 (softIrq * 100) / total);
1498 }
1499 }
1500
Amith Yamasanie43530a2009-08-21 13:11:37 -07001501 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001502 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001503 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001504 synchronized(mPidsSelfLocked) {
1505 if (haveNewCpuStats) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001506 if (mOnBattery) {
1507 int perc = bstats.startAddingCpuLocked();
1508 int totalUTime = 0;
1509 int totalSTime = 0;
Dianne Hackborn287952c2010-09-22 22:34:31 -07001510 final int N = mProcessStats.countStats();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001511 for (int i=0; i<N; i++) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001512 ProcessStats.Stats st = mProcessStats.getStats(i);
1513 if (!st.working) {
1514 continue;
1515 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001516 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001517 int otherUTime = (st.rel_utime*perc)/100;
1518 int otherSTime = (st.rel_stime*perc)/100;
1519 totalUTime += otherUTime;
1520 totalSTime += otherSTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001521 if (pr != null) {
1522 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001523 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1524 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001525 ps.addSpeedStepTimes(cpuSpeedTimes);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001526 pr.curCpuTime += (st.rel_utime+st.rel_stime) * 10;
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001527 } else {
1528 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001529 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001530 if (ps != null) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001531 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1532 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001533 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001534 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001535 }
1536 }
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001537 bstats.finishAddingCpuLocked(perc, totalUTime,
1538 totalSTime, cpuSpeedTimes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001539 }
1540 }
1541 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001542
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001543 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1544 mLastWriteTime = now;
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001545 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001546 }
1547 }
1548 }
1549 }
1550
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001551 @Override
1552 public void batteryNeedsCpuUpdate() {
1553 updateCpuStatsNow();
1554 }
1555
1556 @Override
1557 public void batteryPowerChanged(boolean onBattery) {
1558 // When plugging in, update the CPU stats first before changing
1559 // the plug state.
1560 updateCpuStatsNow();
1561 synchronized (this) {
1562 synchronized(mPidsSelfLocked) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001563 mOnBattery = DEBUG_POWER ? true : onBattery;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001564 }
1565 }
1566 }
1567
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001568 /**
1569 * Initialize the application bind args. These are passed to each
1570 * process when the bindApplication() IPC is sent to the process. They're
1571 * lazily setup to make sure the services are running when they're asked for.
1572 */
1573 private HashMap<String, IBinder> getCommonServicesLocked() {
1574 if (mAppBindArgs == null) {
1575 mAppBindArgs = new HashMap<String, IBinder>();
1576
1577 // Setup the application init args
1578 mAppBindArgs.put("package", ServiceManager.getService("package"));
1579 mAppBindArgs.put("window", ServiceManager.getService("window"));
1580 mAppBindArgs.put(Context.ALARM_SERVICE,
1581 ServiceManager.getService(Context.ALARM_SERVICE));
1582 }
1583 return mAppBindArgs;
1584 }
1585
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001586 final void setFocusedActivityLocked(ActivityRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001587 if (mFocusedActivity != r) {
1588 mFocusedActivity = r;
1589 mWindowManager.setFocusedApp(r, true);
1590 }
1591 }
1592
Dianne Hackborn906497c2010-05-10 15:57:38 -07001593 private final void updateLruProcessInternalLocked(ProcessRecord app,
1594 boolean oomAdj, boolean updateActivityTime, int bestPos) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001595 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001596 int lrui = mLruProcesses.indexOf(app);
1597 if (lrui >= 0) mLruProcesses.remove(lrui);
1598
1599 int i = mLruProcesses.size()-1;
1600 int skipTop = 0;
1601
Dianne Hackborn906497c2010-05-10 15:57:38 -07001602 app.lruSeq = mLruSeq;
1603
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001604 // compute the new weight for this process.
1605 if (updateActivityTime) {
1606 app.lastActivityTime = SystemClock.uptimeMillis();
1607 }
1608 if (app.activities.size() > 0) {
1609 // If this process has activities, we more strongly want to keep
1610 // it around.
1611 app.lruWeight = app.lastActivityTime;
1612 } else if (app.pubProviders.size() > 0) {
1613 // If this process contains content providers, we want to keep
1614 // it a little more strongly.
Dianne Hackborn7d608422011-08-07 16:24:18 -07001615 app.lruWeight = app.lastActivityTime - ProcessList.CONTENT_APP_IDLE_OFFSET;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001616 // Also don't let it kick out the first few "real" hidden processes.
Dianne Hackborn7d608422011-08-07 16:24:18 -07001617 skipTop = ProcessList.MIN_HIDDEN_APPS;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001618 } else {
1619 // If this process doesn't have activities, we less strongly
1620 // want to keep it around, and generally want to avoid getting
1621 // in front of any very recently used activities.
Dianne Hackborn7d608422011-08-07 16:24:18 -07001622 app.lruWeight = app.lastActivityTime - ProcessList.EMPTY_APP_IDLE_OFFSET;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001623 // Also don't let it kick out the first few "real" hidden processes.
Dianne Hackborn7d608422011-08-07 16:24:18 -07001624 skipTop = ProcessList.MIN_HIDDEN_APPS;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001625 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001626
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001627 while (i >= 0) {
1628 ProcessRecord p = mLruProcesses.get(i);
1629 // If this app shouldn't be in front of the first N background
1630 // apps, then skip over that many that are currently hidden.
Dianne Hackborn7d608422011-08-07 16:24:18 -07001631 if (skipTop > 0 && p.setAdj >= ProcessList.HIDDEN_APP_MIN_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001632 skipTop--;
1633 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001634 if (p.lruWeight <= app.lruWeight || i < bestPos) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001635 mLruProcesses.add(i+1, app);
1636 break;
1637 }
1638 i--;
1639 }
1640 if (i < 0) {
1641 mLruProcesses.add(0, app);
1642 }
1643
Dianne Hackborn906497c2010-05-10 15:57:38 -07001644 // If the app is currently using a content provider or service,
1645 // bump those processes as well.
1646 if (app.connections.size() > 0) {
1647 for (ConnectionRecord cr : app.connections) {
1648 if (cr.binding != null && cr.binding.service != null
1649 && cr.binding.service.app != null
1650 && cr.binding.service.app.lruSeq != mLruSeq) {
1651 updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,
1652 updateActivityTime, i+1);
1653 }
1654 }
1655 }
1656 if (app.conProviders.size() > 0) {
1657 for (ContentProviderRecord cpr : app.conProviders.keySet()) {
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07001658 if (cpr.proc != null && cpr.proc.lruSeq != mLruSeq) {
1659 updateLruProcessInternalLocked(cpr.proc, oomAdj,
Dianne Hackborn906497c2010-05-10 15:57:38 -07001660 updateActivityTime, i+1);
1661 }
1662 }
1663 }
1664
Joe Onorato8a9b2202010-02-26 18:56:32 -08001665 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001666 if (oomAdj) {
1667 updateOomAdjLocked();
1668 }
1669 }
1670
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001671 final void updateLruProcessLocked(ProcessRecord app,
Dianne Hackborn906497c2010-05-10 15:57:38 -07001672 boolean oomAdj, boolean updateActivityTime) {
1673 mLruSeq++;
1674 updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
1675 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07001676
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001677 final ProcessRecord getProcessRecordLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001678 String processName, int uid) {
1679 if (uid == Process.SYSTEM_UID) {
1680 // The system gets to run in any process. If there are multiple
1681 // processes with the same uid, just pick the first (this
1682 // should never happen).
1683 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1684 processName);
1685 return procs != null ? procs.valueAt(0) : null;
1686 }
1687 ProcessRecord proc = mProcessNames.get(processName, uid);
1688 return proc;
1689 }
1690
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001691 void ensurePackageDexOpt(String packageName) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001692 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001693 try {
1694 if (pm.performDexOpt(packageName)) {
1695 mDidDexOpt = true;
1696 }
1697 } catch (RemoteException e) {
1698 }
1699 }
1700
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001701 boolean isNextTransitionForward() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001702 int transit = mWindowManager.getPendingAppTransition();
1703 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1704 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1705 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1706 }
1707
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001708 final ProcessRecord startProcessLocked(String processName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001709 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001710 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001711 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1712 // We don't have to do anything more if:
1713 // (1) There is an existing application record; and
1714 // (2) The caller doesn't think it is dead, OR there is no thread
1715 // object attached to it so we know it couldn't have crashed; and
1716 // (3) There is a pid assigned to it, so it is either starting or
1717 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001718 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001719 + " app=" + app + " knownToBeDead=" + knownToBeDead
1720 + " thread=" + (app != null ? app.thread : null)
1721 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01001722 if (app != null && app.pid > 0) {
1723 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001724 // We already have the app running, or are waiting for it to
1725 // come up (we have a pid but not yet its thread), so keep it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001726 if (DEBUG_PROCESSES) Slog.v(TAG, "App already running: " + app);
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001727 // If this is a new package in the process, add the package to the list
1728 app.addPackage(info.packageName);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001729 return app;
1730 } else {
1731 // An application record is attached to a previous process,
1732 // clean it up now.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001733 if (DEBUG_PROCESSES) Slog.v(TAG, "App died: " + app);
Dianne Hackborn130b0d22011-07-26 22:07:48 -07001734 handleAppDiedLocked(app, true, true);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001735 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001736 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01001737
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001738 String hostingNameStr = hostingName != null
1739 ? hostingName.flattenToShortString() : null;
1740
1741 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1742 // If we are in the background, then check to see if this process
1743 // is bad. If so, we will just silently fail.
1744 if (mBadProcesses.get(info.processName, info.uid) != null) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001745 if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid
1746 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001747 return null;
1748 }
1749 } else {
1750 // When the user is explicitly starting a process, then clear its
1751 // crash count so that we won't make it bad until they see at
1752 // least one crash dialog again, and make the process good again
1753 // if it had been bad.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001754 if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
1755 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001756 mProcessCrashTimes.remove(info.processName, info.uid);
1757 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001758 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001759 info.processName);
1760 mBadProcesses.remove(info.processName, info.uid);
1761 if (app != null) {
1762 app.bad = false;
1763 }
1764 }
1765 }
1766
1767 if (app == null) {
1768 app = newProcessRecordLocked(null, info, processName);
1769 mProcessNames.put(processName, info.uid, app);
1770 } else {
1771 // If this is a new package in the process, add the package to the list
1772 app.addPackage(info.packageName);
1773 }
1774
1775 // If the system is not ready yet, then hold off on starting this
1776 // process until it is.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001777 if (!mProcessesReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001778 && !isAllowedWhileBooting(info)
1779 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001780 if (!mProcessesOnHold.contains(app)) {
1781 mProcessesOnHold.add(app);
1782 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001783 if (DEBUG_PROCESSES) Slog.v(TAG, "System not ready, putting on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001784 return app;
1785 }
1786
1787 startProcessLocked(app, hostingType, hostingNameStr);
1788 return (app.pid != 0) ? app : null;
1789 }
1790
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001791 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1792 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1793 }
1794
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001795 private final void startProcessLocked(ProcessRecord app,
1796 String hostingType, String hostingNameStr) {
1797 if (app.pid > 0 && app.pid != MY_PID) {
1798 synchronized (mPidsSelfLocked) {
1799 mPidsSelfLocked.remove(app.pid);
1800 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1801 }
1802 app.pid = 0;
1803 }
1804
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001805 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
1806 "startProcessLocked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001807 mProcessesOnHold.remove(app);
1808
1809 updateCpuStats();
1810
1811 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1812 mProcDeaths[0] = 0;
1813
1814 try {
1815 int uid = app.info.uid;
1816 int[] gids = null;
1817 try {
1818 gids = mContext.getPackageManager().getPackageGids(
1819 app.info.packageName);
1820 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001821 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001822 }
1823 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1824 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1825 && mTopComponent != null
1826 && app.processName.equals(mTopComponent.getPackageName())) {
1827 uid = 0;
1828 }
1829 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1830 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1831 uid = 0;
1832 }
1833 }
1834 int debugFlags = 0;
1835 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1836 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
Elliott Hughesfa36aee2011-06-17 14:39:41 -07001837 // Also turn on CheckJNI for debuggable apps. It's quite
1838 // awkward to turn on otherwise.
1839 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001840 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08001841 // Run the app in safe mode if its manifest requests so or the
1842 // system is booted in safe mode.
1843 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
1844 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08001845 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1846 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001847 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1848 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1849 }
Elliott Hughesae07ecf2011-07-06 17:33:27 -07001850 if ("1".equals(SystemProperties.get("debug.jni.logging"))) {
1851 debugFlags |= Zygote.DEBUG_ENABLE_JNI_LOGGING;
1852 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001853 if ("1".equals(SystemProperties.get("debug.assert"))) {
1854 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1855 }
Jeff Brown3f9dd282011-07-08 20:02:19 -07001856
1857 // Start the process. It will either succeed and return a result containing
1858 // the PID of the new process, or else throw a RuntimeException.
1859 Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
Elliott Hughese1dfcb72011-07-08 11:08:07 -07001860 app.processName, uid, uid, gids, debugFlags,
1861 app.info.targetSdkVersion, null);
Jeff Brown3f9dd282011-07-08 20:02:19 -07001862
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001863 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
1864 synchronized (bs) {
1865 if (bs.isOnBattery()) {
1866 app.batteryStats.incStartsLocked();
1867 }
1868 }
1869
Jeff Brown3f9dd282011-07-08 20:02:19 -07001870 EventLog.writeEvent(EventLogTags.AM_PROC_START, startResult.pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001871 app.processName, hostingType,
1872 hostingNameStr != null ? hostingNameStr : "");
1873
1874 if (app.persistent) {
Jeff Brown3f9dd282011-07-08 20:02:19 -07001875 Watchdog.getInstance().processStarted(app.processName, startResult.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001876 }
1877
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07001878 StringBuilder buf = mStringBuilder;
1879 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001880 buf.append("Start proc ");
1881 buf.append(app.processName);
1882 buf.append(" for ");
1883 buf.append(hostingType);
1884 if (hostingNameStr != null) {
1885 buf.append(" ");
1886 buf.append(hostingNameStr);
1887 }
1888 buf.append(": pid=");
Jeff Brown3f9dd282011-07-08 20:02:19 -07001889 buf.append(startResult.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001890 buf.append(" uid=");
1891 buf.append(uid);
1892 buf.append(" gids={");
1893 if (gids != null) {
1894 for (int gi=0; gi<gids.length; gi++) {
1895 if (gi != 0) buf.append(", ");
1896 buf.append(gids[gi]);
1897
1898 }
1899 }
1900 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08001901 Slog.i(TAG, buf.toString());
Jeff Brown3f9dd282011-07-08 20:02:19 -07001902 app.pid = startResult.pid;
1903 app.usingWrapper = startResult.usingWrapper;
1904 app.removed = false;
1905 synchronized (mPidsSelfLocked) {
1906 this.mPidsSelfLocked.put(startResult.pid, app);
1907 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1908 msg.obj = app;
1909 mHandler.sendMessageDelayed(msg, startResult.usingWrapper
1910 ? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001911 }
1912 } catch (RuntimeException e) {
1913 // XXX do better error recovery.
1914 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001915 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001916 }
1917 }
1918
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001919 void updateUsageStats(ActivityRecord resumedComponent, boolean resumed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001920 if (resumed) {
1921 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
1922 } else {
1923 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
1924 }
1925 }
1926
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001927 boolean startHomeActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001928 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1929 && mTopAction == null) {
1930 // We are running in factory test mode, but unable to find
1931 // the factory test app, so just sit around displaying the
1932 // error message and don't try to start anything.
1933 return false;
1934 }
1935 Intent intent = new Intent(
1936 mTopAction,
1937 mTopData != null ? Uri.parse(mTopData) : null);
1938 intent.setComponent(mTopComponent);
1939 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
1940 intent.addCategory(Intent.CATEGORY_HOME);
1941 }
1942 ActivityInfo aInfo =
1943 intent.resolveActivityInfo(mContext.getPackageManager(),
1944 STOCK_PM_FLAGS);
1945 if (aInfo != null) {
1946 intent.setComponent(new ComponentName(
1947 aInfo.applicationInfo.packageName, aInfo.name));
1948 // Don't do this if the home app is currently being
1949 // instrumented.
1950 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
1951 aInfo.applicationInfo.uid);
1952 if (app == null || app.instrumentationClass == null) {
1953 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001954 mMainStack.startActivityLocked(null, intent, null, null, 0, aInfo,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001955 null, null, 0, 0, 0, false, false, null);
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001956 }
1957 }
1958
1959
1960 return true;
1961 }
1962
1963 /**
1964 * Starts the "new version setup screen" if appropriate.
1965 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001966 void startSetupActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07001967 // Only do this once per boot.
1968 if (mCheckedForSetup) {
1969 return;
1970 }
1971
1972 // We will show this screen if the current one is a different
1973 // version than the last one shown, and we are not running in
1974 // low-level factory test mode.
1975 final ContentResolver resolver = mContext.getContentResolver();
1976 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
1977 Settings.Secure.getInt(resolver,
1978 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
1979 mCheckedForSetup = true;
1980
1981 // See if we should be showing the platform update setup UI.
1982 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
1983 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
1984 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
1985
1986 // We don't allow third party apps to replace this.
1987 ResolveInfo ri = null;
1988 for (int i=0; ris != null && i<ris.size(); i++) {
1989 if ((ris.get(i).activityInfo.applicationInfo.flags
1990 & ApplicationInfo.FLAG_SYSTEM) != 0) {
1991 ri = ris.get(i);
1992 break;
1993 }
1994 }
1995
1996 if (ri != null) {
1997 String vers = ri.activityInfo.metaData != null
1998 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
1999 : null;
2000 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
2001 vers = ri.activityInfo.applicationInfo.metaData.getString(
2002 Intent.METADATA_SETUP_VERSION);
2003 }
2004 String lastVers = Settings.Secure.getString(
2005 resolver, Settings.Secure.LAST_SETUP_SHOWN);
2006 if (vers != null && !vers.equals(lastVers)) {
2007 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2008 intent.setComponent(new ComponentName(
2009 ri.activityInfo.packageName, ri.activityInfo.name));
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002010 mMainStack.startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002011 null, null, 0, 0, 0, false, false, null);
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002012 }
2013 }
2014 }
2015 }
2016
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002017 CompatibilityInfo compatibilityInfoForPackageLocked(ApplicationInfo ai) {
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002018 return mCompatModePackages.compatibilityInfoForPackageLocked(ai);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002019 }
2020
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002021 public int getFrontActivityScreenCompatMode() {
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002022 synchronized (this) {
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002023 return mCompatModePackages.getFrontActivityScreenCompatModeLocked();
2024 }
2025 }
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002026
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002027 public void setFrontActivityScreenCompatMode(int mode) {
2028 synchronized (this) {
2029 mCompatModePackages.setFrontActivityScreenCompatModeLocked(mode);
2030 }
2031 }
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002032
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002033 public int getPackageScreenCompatMode(String packageName) {
2034 synchronized (this) {
2035 return mCompatModePackages.getPackageScreenCompatModeLocked(packageName);
2036 }
2037 }
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002038
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002039 public void setPackageScreenCompatMode(String packageName, int mode) {
2040 synchronized (this) {
2041 mCompatModePackages.setPackageScreenCompatModeLocked(packageName, mode);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002042 }
2043 }
2044
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07002045 public boolean getPackageAskScreenCompat(String packageName) {
2046 synchronized (this) {
2047 return mCompatModePackages.getPackageAskCompatModeLocked(packageName);
2048 }
2049 }
2050
2051 public void setPackageAskScreenCompat(String packageName, boolean ask) {
2052 synchronized (this) {
2053 mCompatModePackages.setPackageAskCompatModeLocked(packageName, ask);
2054 }
2055 }
2056
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002057 void reportResumedActivityLocked(ActivityRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002058 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002059
2060 final int identHash = System.identityHashCode(r);
2061 updateUsageStats(r, true);
2062
2063 int i = mWatchers.beginBroadcast();
2064 while (i > 0) {
2065 i--;
2066 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2067 if (w != null) {
2068 try {
2069 w.activityResuming(identHash);
2070 } catch (RemoteException e) {
2071 }
2072 }
2073 }
2074 mWatchers.finishBroadcast();
2075 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002076
Jeff Sharkeya4620792011-05-20 15:29:23 -07002077 private void dispatchForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities) {
2078 int i = mProcessObservers.beginBroadcast();
2079 while (i > 0) {
2080 i--;
2081 final IProcessObserver observer = mProcessObservers.getBroadcastItem(i);
2082 if (observer != null) {
2083 try {
2084 observer.onForegroundActivitiesChanged(pid, uid, foregroundActivities);
2085 } catch (RemoteException e) {
2086 }
2087 }
2088 }
2089 mProcessObservers.finishBroadcast();
2090 }
2091
2092 private void dispatchProcessDied(int pid, int uid) {
2093 int i = mProcessObservers.beginBroadcast();
2094 while (i > 0) {
2095 i--;
2096 final IProcessObserver observer = mProcessObservers.getBroadcastItem(i);
2097 if (observer != null) {
2098 try {
2099 observer.onProcessDied(pid, uid);
2100 } catch (RemoteException e) {
2101 }
2102 }
2103 }
2104 mProcessObservers.finishBroadcast();
2105 }
2106
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002107 final void doPendingActivityLaunchesLocked(boolean doResume) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002108 final int N = mPendingActivityLaunches.size();
2109 if (N <= 0) {
2110 return;
2111 }
2112 for (int i=0; i<N; i++) {
2113 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002114 mMainStack.startActivityUncheckedLocked(pal.r, pal.sourceRecord,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002115 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
2116 doResume && i == (N-1));
2117 }
2118 mPendingActivityLaunches.clear();
2119 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002120
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002121 public final int startActivity(IApplicationThread caller,
2122 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2123 int grantedMode, IBinder resultTo,
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07002124 String resultWho, int requestCode, boolean onlyIfNeeded, boolean debug,
2125 String profileFile, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002126 return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002127 grantedUriPermissions, grantedMode, resultTo, resultWho,
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07002128 requestCode, onlyIfNeeded, debug, profileFile, profileFd, autoStopProfiler,
2129 null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002130 }
2131
2132 public final WaitResult startActivityAndWait(IApplicationThread caller,
2133 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2134 int grantedMode, IBinder resultTo,
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07002135 String resultWho, int requestCode, boolean onlyIfNeeded, boolean debug,
2136 String profileFile, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002137 WaitResult res = new WaitResult();
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002138 mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002139 grantedUriPermissions, grantedMode, resultTo, resultWho,
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07002140 requestCode, onlyIfNeeded, debug, profileFile, profileFd, autoStopProfiler,
2141 res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002142 return res;
2143 }
2144
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002145 public final int startActivityWithConfig(IApplicationThread caller,
2146 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2147 int grantedMode, IBinder resultTo,
2148 String resultWho, int requestCode, boolean onlyIfNeeded,
2149 boolean debug, Configuration config) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002150 return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002151 grantedUriPermissions, grantedMode, resultTo, resultWho,
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07002152 requestCode, onlyIfNeeded, debug, null, null, false, null, config);
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002153 }
2154
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002155 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002156 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002157 IBinder resultTo, String resultWho, int requestCode,
2158 int flagsMask, int flagsValues) {
2159 // Refuse possible leaked file descriptors
2160 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
2161 throw new IllegalArgumentException("File descriptors passed in Intent");
2162 }
2163
2164 IIntentSender sender = intent.getTarget();
2165 if (!(sender instanceof PendingIntentRecord)) {
2166 throw new IllegalArgumentException("Bad PendingIntent object");
2167 }
2168
2169 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002170
2171 synchronized (this) {
2172 // If this is coming from the currently resumed activity, it is
2173 // effectively saying that app switches are allowed at this point.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002174 if (mMainStack.mResumedActivity != null
2175 && mMainStack.mResumedActivity.info.applicationInfo.uid ==
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002176 Binder.getCallingUid()) {
2177 mAppSwitchesAllowedTime = 0;
2178 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002179 }
2180
Dianne Hackborn6c418d52011-06-29 14:05:33 -07002181 return pir.sendInner(0, fillInIntent, resolvedType, null,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002182 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
2183 }
2184
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002185 public boolean startNextMatchingActivity(IBinder callingActivity,
2186 Intent intent) {
2187 // Refuse possible leaked file descriptors
2188 if (intent != null && intent.hasFileDescriptors() == true) {
2189 throw new IllegalArgumentException("File descriptors passed in Intent");
2190 }
2191
2192 synchronized (this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07002193 ActivityRecord r = mMainStack.isInStackLocked(callingActivity);
2194 if (r == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002195 return false;
2196 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002197 if (r.app == null || r.app.thread == null) {
2198 // The caller is not running... d'oh!
2199 return false;
2200 }
2201 intent = new Intent(intent);
2202 // The caller is not allowed to change the data.
2203 intent.setDataAndType(r.intent.getData(), r.intent.getType());
2204 // And we are resetting to find the next component...
2205 intent.setComponent(null);
2206
2207 ActivityInfo aInfo = null;
2208 try {
2209 List<ResolveInfo> resolves =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002210 AppGlobals.getPackageManager().queryIntentActivities(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002211 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002212 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002213
2214 // Look for the original activity in the list...
2215 final int N = resolves != null ? resolves.size() : 0;
2216 for (int i=0; i<N; i++) {
2217 ResolveInfo rInfo = resolves.get(i);
2218 if (rInfo.activityInfo.packageName.equals(r.packageName)
2219 && rInfo.activityInfo.name.equals(r.info.name)) {
2220 // We found the current one... the next matching is
2221 // after it.
2222 i++;
2223 if (i<N) {
2224 aInfo = resolves.get(i).activityInfo;
2225 }
2226 break;
2227 }
2228 }
2229 } catch (RemoteException e) {
2230 }
2231
2232 if (aInfo == null) {
2233 // Nobody who is next!
2234 return false;
2235 }
2236
2237 intent.setComponent(new ComponentName(
2238 aInfo.applicationInfo.packageName, aInfo.name));
2239 intent.setFlags(intent.getFlags()&~(
2240 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
2241 Intent.FLAG_ACTIVITY_CLEAR_TOP|
2242 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
2243 Intent.FLAG_ACTIVITY_NEW_TASK));
2244
2245 // Okay now we need to start the new activity, replacing the
2246 // currently running activity. This is a little tricky because
2247 // we want to start the new one as if the current one is finished,
2248 // but not finish the current one first so that there is no flicker.
2249 // And thus...
2250 final boolean wasFinishing = r.finishing;
2251 r.finishing = true;
2252
2253 // Propagate reply information over to the new activity.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002254 final ActivityRecord resultTo = r.resultTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002255 final String resultWho = r.resultWho;
2256 final int requestCode = r.requestCode;
2257 r.resultTo = null;
2258 if (resultTo != null) {
2259 resultTo.removeResultsLocked(r, resultWho, requestCode);
2260 }
2261
2262 final long origId = Binder.clearCallingIdentity();
2263 // XXX we are not dealing with propagating grantedUriPermissions...
2264 // those are not yet exposed to user code, so there is no need.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002265 int res = mMainStack.startActivityLocked(r.app.thread, intent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002266 r.resolvedType, null, 0, aInfo, resultTo, resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002267 requestCode, -1, r.launchedFromUid, false, false, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002268 Binder.restoreCallingIdentity(origId);
2269
2270 r.finishing = wasFinishing;
2271 if (res != START_SUCCESS) {
2272 return false;
2273 }
2274 return true;
2275 }
2276 }
2277
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002278 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002279 Intent intent, String resolvedType, IBinder resultTo,
2280 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002281
2282 // This is so super not safe, that only the system (or okay root)
2283 // can do it.
2284 final int callingUid = Binder.getCallingUid();
2285 if (callingUid != 0 && callingUid != Process.myUid()) {
2286 throw new SecurityException(
2287 "startActivityInPackage only available to the system");
2288 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002289
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002290 return mMainStack.startActivityMayWait(null, uid, intent, resolvedType,
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07002291 null, 0, resultTo, resultWho, requestCode, onlyIfNeeded, false,
2292 null, null, false, null, null);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002293 }
2294
2295 public final int startActivities(IApplicationThread caller,
2296 Intent[] intents, String[] resolvedTypes, IBinder resultTo) {
2297 return mMainStack.startActivities(caller, -1, intents, resolvedTypes, resultTo);
2298 }
2299
2300 public final int startActivitiesInPackage(int uid,
2301 Intent[] intents, String[] resolvedTypes, IBinder resultTo) {
2302
2303 // This is so super not safe, that only the system (or okay root)
2304 // can do it.
2305 final int callingUid = Binder.getCallingUid();
2306 if (callingUid != 0 && callingUid != Process.myUid()) {
2307 throw new SecurityException(
2308 "startActivityInPackage only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002309 }
2310
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002311 return mMainStack.startActivities(null, uid, intents, resolvedTypes, resultTo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002312 }
2313
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002314 final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002315 int N = mRecentTasks.size();
Dianne Hackborn7c0e75e2010-12-21 19:15:40 -08002316 // Quick case: check if the top-most recent task is the same.
2317 if (N > 0 && mRecentTasks.get(0) == task) {
2318 return;
2319 }
2320 // Remove any existing entries that are the same kind of task.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002321 for (int i=0; i<N; i++) {
2322 TaskRecord tr = mRecentTasks.get(i);
2323 if ((task.affinity != null && task.affinity.equals(tr.affinity))
2324 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
2325 mRecentTasks.remove(i);
2326 i--;
2327 N--;
2328 if (task.intent == null) {
2329 // If the new recent task we are adding is not fully
2330 // specified, then replace it with the existing recent task.
2331 task = tr;
2332 }
2333 }
2334 }
2335 if (N >= MAX_RECENT_TASKS) {
2336 mRecentTasks.remove(N-1);
2337 }
2338 mRecentTasks.add(0, task);
2339 }
2340
2341 public void setRequestedOrientation(IBinder token,
2342 int requestedOrientation) {
2343 synchronized (this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07002344 ActivityRecord r = mMainStack.isInStackLocked(token);
2345 if (r == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002346 return;
2347 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002348 final long origId = Binder.clearCallingIdentity();
2349 mWindowManager.setAppOrientation(r, requestedOrientation);
2350 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07002351 mConfiguration,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002352 r.mayFreezeScreenLocked(r.app) ? r : null);
2353 if (config != null) {
2354 r.frozenBeforeDestroy = true;
Dianne Hackborn31ca8542011-07-19 14:58:28 -07002355 if (!updateConfigurationLocked(config, r, false)) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002356 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002357 }
2358 }
2359 Binder.restoreCallingIdentity(origId);
2360 }
2361 }
2362
2363 public int getRequestedOrientation(IBinder token) {
2364 synchronized (this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07002365 ActivityRecord r = mMainStack.isInStackLocked(token);
2366 if (r == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002367 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
2368 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002369 return mWindowManager.getAppOrientation(r);
2370 }
2371 }
2372
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002373 /**
2374 * This is the internal entry point for handling Activity.finish().
2375 *
2376 * @param token The Binder token referencing the Activity we want to finish.
2377 * @param resultCode Result code, if any, from this Activity.
2378 * @param resultData Result data (Intent), if any, from this Activity.
2379 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11002380 * @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 -08002381 */
2382 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
2383 // Refuse possible leaked file descriptors
2384 if (resultData != null && resultData.hasFileDescriptors() == true) {
2385 throw new IllegalArgumentException("File descriptors passed in Intent");
2386 }
2387
2388 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002389 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002390 // Find the first activity that is not finishing.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002391 ActivityRecord next = mMainStack.topRunningActivityLocked(token, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002392 if (next != null) {
2393 // ask watcher if this is allowed
2394 boolean resumeOK = true;
2395 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002396 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002397 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002398 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002399 }
2400
2401 if (!resumeOK) {
2402 return false;
2403 }
2404 }
2405 }
2406 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002407 boolean res = mMainStack.requestFinishActivityLocked(token, resultCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002408 resultData, "app-request");
2409 Binder.restoreCallingIdentity(origId);
2410 return res;
2411 }
2412 }
2413
Dianne Hackborn860755f2010-06-03 18:47:52 -07002414 public final void finishHeavyWeightApp() {
2415 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2416 != PackageManager.PERMISSION_GRANTED) {
2417 String msg = "Permission Denial: finishHeavyWeightApp() from pid="
2418 + Binder.getCallingPid()
2419 + ", uid=" + Binder.getCallingUid()
2420 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2421 Slog.w(TAG, msg);
2422 throw new SecurityException(msg);
2423 }
2424
2425 synchronized(this) {
2426 if (mHeavyWeightProcess == null) {
2427 return;
2428 }
2429
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002430 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>(
Dianne Hackborn860755f2010-06-03 18:47:52 -07002431 mHeavyWeightProcess.activities);
2432 for (int i=0; i<activities.size(); i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002433 ActivityRecord r = activities.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002434 if (!r.finishing) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002435 int index = mMainStack.indexOfTokenLocked(r);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002436 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002437 mMainStack.finishActivityLocked(r, index, Activity.RESULT_CANCELED,
Dianne Hackborn860755f2010-06-03 18:47:52 -07002438 null, "finish-heavy");
2439 }
2440 }
2441 }
2442
2443 mHeavyWeightProcess = null;
2444 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
2445 }
2446 }
2447
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002448 public void crashApplication(int uid, int initialPid, String packageName,
2449 String message) {
2450 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2451 != PackageManager.PERMISSION_GRANTED) {
2452 String msg = "Permission Denial: crashApplication() from pid="
2453 + Binder.getCallingPid()
2454 + ", uid=" + Binder.getCallingUid()
2455 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2456 Slog.w(TAG, msg);
2457 throw new SecurityException(msg);
2458 }
2459
2460 synchronized(this) {
2461 ProcessRecord proc = null;
2462
2463 // Figure out which process to kill. We don't trust that initialPid
2464 // still has any relation to current pids, so must scan through the
2465 // list.
2466 synchronized (mPidsSelfLocked) {
2467 for (int i=0; i<mPidsSelfLocked.size(); i++) {
2468 ProcessRecord p = mPidsSelfLocked.valueAt(i);
2469 if (p.info.uid != uid) {
2470 continue;
2471 }
2472 if (p.pid == initialPid) {
2473 proc = p;
2474 break;
2475 }
2476 for (String str : p.pkgList) {
2477 if (str.equals(packageName)) {
2478 proc = p;
2479 }
2480 }
2481 }
2482 }
2483
2484 if (proc == null) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07002485 Slog.w(TAG, "crashApplication: nothing for uid=" + uid
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002486 + " initialPid=" + initialPid
2487 + " packageName=" + packageName);
2488 return;
2489 }
2490
2491 if (proc.thread != null) {
Dianne Hackborn9f531192010-08-04 17:48:03 -07002492 if (proc.pid == Process.myPid()) {
2493 Log.w(TAG, "crashApplication: trying to crash self!");
2494 return;
2495 }
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002496 long ident = Binder.clearCallingIdentity();
2497 try {
2498 proc.thread.scheduleCrash(message);
2499 } catch (RemoteException e) {
2500 }
2501 Binder.restoreCallingIdentity(ident);
2502 }
2503 }
2504 }
2505
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002506 public final void finishSubActivity(IBinder token, String resultWho,
2507 int requestCode) {
2508 synchronized(this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07002509 ActivityRecord self = mMainStack.isInStackLocked(token);
2510 if (self == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002511 return;
2512 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002513
2514 final long origId = Binder.clearCallingIdentity();
2515
2516 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002517 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2518 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002519 if (r.resultTo == self && r.requestCode == requestCode) {
2520 if ((r.resultWho == null && resultWho == null) ||
2521 (r.resultWho != null && r.resultWho.equals(resultWho))) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002522 mMainStack.finishActivityLocked(r, i,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002523 Activity.RESULT_CANCELED, null, "request-sub");
2524 }
2525 }
2526 }
2527
2528 Binder.restoreCallingIdentity(origId);
2529 }
2530 }
2531
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002532 public boolean willActivityBeVisible(IBinder token) {
2533 synchronized(this) {
2534 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002535 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2536 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002537 if (r == token) {
2538 return true;
2539 }
2540 if (r.fullscreen && !r.finishing) {
2541 return false;
2542 }
2543 }
2544 return true;
2545 }
2546 }
2547
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002548 public void overridePendingTransition(IBinder token, String packageName,
2549 int enterAnim, int exitAnim) {
2550 synchronized(this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07002551 ActivityRecord self = mMainStack.isInStackLocked(token);
2552 if (self == null) {
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002553 return;
2554 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002555
2556 final long origId = Binder.clearCallingIdentity();
2557
2558 if (self.state == ActivityState.RESUMED
2559 || self.state == ActivityState.PAUSING) {
2560 mWindowManager.overridePendingAppTransition(packageName,
2561 enterAnim, exitAnim);
2562 }
2563
2564 Binder.restoreCallingIdentity(origId);
2565 }
2566 }
2567
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002568 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002569 * Main function for removing an existing process from the activity manager
2570 * as a result of that process going away. Clears out all connections
2571 * to the process.
2572 */
2573 private final void handleAppDiedLocked(ProcessRecord app,
Dianne Hackborn130b0d22011-07-26 22:07:48 -07002574 boolean restarting, boolean allowRestart) {
2575 cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002576 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002577 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002578 }
2579
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07002580 if (mProfileProc == app) {
2581 clearProfilerLocked();
2582 }
2583
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002584 // Just in case...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002585 if (mMainStack.mPausingActivity != null && mMainStack.mPausingActivity.app == app) {
2586 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " +mMainStack.mPausingActivity);
2587 mMainStack.mPausingActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002588 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002589 if (mMainStack.mLastPausedActivity != null && mMainStack.mLastPausedActivity.app == app) {
2590 mMainStack.mLastPausedActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002591 }
2592
2593 // Remove this application's activities from active lists.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002594 mMainStack.removeHistoryRecordsForAppLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002595
2596 boolean atTop = true;
2597 boolean hasVisibleActivities = false;
2598
2599 // Clean out the history list.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002600 int i = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002601 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002602 TAG, "Removing app " + app + " from history with " + i + " entries");
2603 while (i > 0) {
2604 i--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002605 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002606 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002607 TAG, "Record #" + i + " " + r + ": app=" + r.app);
2608 if (r.app == app) {
2609 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Dianne Hackborn98cfebc2011-10-18 13:17:33 -07002610 if (ActivityStack.DEBUG_ADD_REMOVE) {
2611 RuntimeException here = new RuntimeException("here");
2612 here.fillInStackTrace();
2613 Slog.i(TAG, "Removing activity " + r + " from stack at " + i
2614 + ": haveState=" + r.haveState
2615 + " stateNotNeeded=" + r.stateNotNeeded
2616 + " finishing=" + r.finishing
2617 + " state=" + r.state, here);
2618 }
2619 if (!r.finishing) {
2620 Slog.w(TAG, "Force removing " + r + ": app died, no saved state");
2621 }
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -08002622 r.makeFinishing();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002623 mMainStack.mHistory.remove(i);
Dianne Hackbornf26fd992011-04-08 18:14:09 -07002624 r.takeFromHistory();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002625 mWindowManager.removeAppToken(r);
2626 if (VALIDATE_TOKENS) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002627 mWindowManager.validateAppTokens(mMainStack.mHistory);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002628 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002629 r.removeUriPermissionsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002630
2631 } else {
2632 // We have the current state for this activity, so
2633 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002634 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002635 TAG, "Keeping entry, setting app to null");
2636 if (r.visible) {
2637 hasVisibleActivities = true;
2638 }
2639 r.app = null;
2640 r.nowVisible = false;
2641 if (!r.haveState) {
Dianne Hackborn98cfebc2011-10-18 13:17:33 -07002642 if (ActivityStack.DEBUG_SAVED_STATE) Slog.i(TAG,
2643 "App died, clearing saved state of " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002644 r.icicle = null;
2645 }
2646 }
2647
Dianne Hackbornce86ba82011-07-13 19:33:41 -07002648 r.stack.cleanUpActivityLocked(r, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002649 }
2650 atTop = false;
2651 }
2652
2653 app.activities.clear();
2654
2655 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002656 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002657 + " running instrumentation " + app.instrumentationClass);
2658 Bundle info = new Bundle();
2659 info.putString("shortMsg", "Process crashed.");
2660 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
2661 }
2662
2663 if (!restarting) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002664 if (!mMainStack.resumeTopActivityLocked(null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002665 // If there was nothing to resume, and we are not already
2666 // restarting this process, but there is a visible activity that
2667 // is hosted by the process... then make sure all visible
2668 // activities are running, taking care of restarting this
2669 // process.
2670 if (hasVisibleActivities) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002671 mMainStack.ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002672 }
2673 }
2674 }
2675 }
2676
2677 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
2678 IBinder threadBinder = thread.asBinder();
2679
2680 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002681 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2682 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002683 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
2684 return i;
2685 }
2686 }
2687 return -1;
2688 }
2689
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002690 final ProcessRecord getRecordForAppLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002691 IApplicationThread thread) {
2692 if (thread == null) {
2693 return null;
2694 }
2695
2696 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002697 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002698 }
2699
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002700 final void appDiedLocked(ProcessRecord app, int pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002701 IApplicationThread thread) {
2702
2703 mProcDeaths[0]++;
2704
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07002705 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
2706 synchronized (stats) {
2707 stats.noteProcessDiedLocked(app.info.uid, pid);
2708 }
2709
Magnus Edlund7bb25812010-02-24 15:45:06 +01002710 // Clean up already done if the process has been re-started.
2711 if (app.pid == pid && app.thread != null &&
2712 app.thread.asBinder() == thread.asBinder()) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07002713 if (!app.killedBackground) {
2714 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
2715 + ") has died.");
2716 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08002717 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002718 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002719 TAG, "Dying app: " + app + ", pid: " + pid
2720 + ", thread: " + thread.asBinder());
2721 boolean doLowMem = app.instrumentationClass == null;
Dianne Hackborn130b0d22011-07-26 22:07:48 -07002722 handleAppDiedLocked(app, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002723
2724 if (doLowMem) {
2725 // If there are no longer any background processes running,
2726 // and the app that died was not running instrumentation,
2727 // then tell everyone we are now low on memory.
2728 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002729 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2730 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn7d608422011-08-07 16:24:18 -07002731 if (rec.thread != null && rec.setAdj >= ProcessList.HIDDEN_APP_MIN_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002732 haveBg = true;
2733 break;
2734 }
2735 }
2736
2737 if (!haveBg) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002738 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002739 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002740 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2741 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07002742 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002743 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
2744 // The low memory report is overriding any current
2745 // state for a GC request. Make sure to do
Dianne Hackborn32907cf2010-06-10 17:50:20 -07002746 // heavy/important/visible/foreground processes first.
Dianne Hackborn7d608422011-08-07 16:24:18 -07002747 if (rec.setAdj <= ProcessList.HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002748 rec.lastRequestedGc = 0;
2749 } else {
2750 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002751 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002752 rec.reportLowMemory = true;
2753 rec.lastLowMemory = now;
2754 mProcessesToGc.remove(rec);
2755 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002756 }
2757 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002758 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002759 }
2760 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01002761 } else if (app.pid != pid) {
2762 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002763 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01002764 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08002765 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002766 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002767 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002768 + thread.asBinder());
2769 }
2770 }
2771
Dan Egnor42471dd2010-01-07 17:25:22 -08002772 /**
2773 * If a stack trace dump file is configured, dump process stack traces.
Christopher Tate6ee412d2010-05-28 12:01:56 -07002774 * @param clearTraces causes the dump file to be erased prior to the new
2775 * traces being written, if true; when false, the new traces will be
2776 * appended to any existing file content.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002777 * @param firstPids of dalvik VM processes to dump stack traces for first
2778 * @param lastPids of dalvik VM processes to dump stack traces for last
Dan Egnor42471dd2010-01-07 17:25:22 -08002779 * @return file containing stack traces, or null if no dump file is configured
2780 */
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002781 public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> firstPids,
2782 ProcessStats processStats, SparseArray<Boolean> lastPids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002783 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
2784 if (tracesPath == null || tracesPath.length() == 0) {
2785 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002786 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002787
2788 File tracesFile = new File(tracesPath);
2789 try {
2790 File tracesDir = tracesFile.getParentFile();
2791 if (!tracesDir.exists()) tracesFile.mkdirs();
2792 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
2793
Christopher Tate6ee412d2010-05-28 12:01:56 -07002794 if (clearTraces && tracesFile.exists()) tracesFile.delete();
Dan Egnor42471dd2010-01-07 17:25:22 -08002795 tracesFile.createNewFile();
2796 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
2797 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002798 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08002799 return null;
2800 }
2801
2802 // Use a FileObserver to detect when traces finish writing.
2803 // The order of traces is considered important to maintain for legibility.
2804 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
2805 public synchronized void onEvent(int event, String path) { notify(); }
2806 };
2807
2808 try {
2809 observer.startWatching();
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002810
2811 // First collect all of the stacks of the most important pids.
2812 try {
2813 int num = firstPids.size();
2814 for (int i = 0; i < num; i++) {
2815 synchronized (observer) {
2816 Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT);
2817 observer.wait(200); // Wait for write-close, give up after 200msec
2818 }
2819 }
2820 } catch (InterruptedException e) {
2821 Log.wtf(TAG, e);
2822 }
2823
2824 // Next measure CPU usage.
2825 if (processStats != null) {
2826 processStats.init();
2827 System.gc();
2828 processStats.update();
2829 try {
2830 synchronized (processStats) {
2831 processStats.wait(500); // measure over 1/2 second.
2832 }
2833 } catch (InterruptedException e) {
2834 }
2835 processStats.update();
2836
2837 // We'll take the stack crawls of just the top apps using CPU.
2838 final int N = processStats.countWorkingStats();
2839 int numProcs = 0;
2840 for (int i=0; i<N && numProcs<5; i++) {
2841 ProcessStats.Stats stats = processStats.getWorkingStats(i);
2842 if (lastPids.indexOfKey(stats.pid) >= 0) {
2843 numProcs++;
2844 try {
2845 synchronized (observer) {
2846 Process.sendSignal(stats.pid, Process.SIGNAL_QUIT);
2847 observer.wait(200); // Wait for write-close, give up after 200msec
2848 }
2849 } catch (InterruptedException e) {
2850 Log.wtf(TAG, e);
2851 }
2852
2853 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002854 }
2855 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002856
2857 return tracesFile;
2858
Dan Egnor42471dd2010-01-07 17:25:22 -08002859 } finally {
2860 observer.stopWatching();
2861 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002862 }
2863
Jeff Brown4d94a762010-09-23 11:33:28 -07002864 private final class AppNotResponding implements Runnable {
2865 private final ProcessRecord mApp;
2866 private final String mAnnotation;
2867
2868 public AppNotResponding(ProcessRecord app, String annotation) {
2869 mApp = app;
2870 mAnnotation = annotation;
2871 }
2872
2873 @Override
2874 public void run() {
2875 appNotResponding(mApp, null, null, mAnnotation);
2876 }
2877 }
2878
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002879 final void appNotResponding(ProcessRecord app, ActivityRecord activity,
2880 ActivityRecord parent, final String annotation) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002881 ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
2882 SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20);
2883
Dianne Hackborn287952c2010-09-22 22:34:31 -07002884 if (mController != null) {
2885 try {
2886 // 0 == continue, -1 = kill process immediately
2887 int res = mController.appEarlyNotResponding(app.processName, app.pid, annotation);
2888 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2889 } catch (RemoteException e) {
2890 mController = null;
2891 }
2892 }
2893
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002894 long anrTime = SystemClock.uptimeMillis();
2895 if (MONITOR_CPU_USAGE) {
2896 updateCpuStatsNow();
2897 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002898
2899 synchronized (this) {
2900 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
2901 if (mShuttingDown) {
2902 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
2903 return;
2904 } else if (app.notResponding) {
2905 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
2906 return;
2907 } else if (app.crashing) {
2908 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
2909 return;
2910 }
2911
2912 // In case we come through here for the same app before completing
2913 // this one, mark as anring now so we will bail out.
2914 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08002915
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002916 // Log the ANR to the event log.
2917 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
2918 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08002919
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002920 // Dump thread traces as quickly as we can, starting with "interesting" processes.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002921 firstPids.add(app.pid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002922
2923 int parentPid = app.pid;
2924 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002925 if (parentPid != app.pid) firstPids.add(parentPid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002926
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002927 if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08002928
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002929 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
2930 ProcessRecord r = mLruProcesses.get(i);
2931 if (r != null && r.thread != null) {
2932 int pid = r.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002933 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
2934 if (r.persistent) {
2935 firstPids.add(pid);
2936 } else {
2937 lastPids.put(pid, Boolean.TRUE);
2938 }
2939 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002940 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002941 }
2942 }
2943
Dan Egnor42471dd2010-01-07 17:25:22 -08002944 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002945 StringBuilder info = mStringBuilder;
2946 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08002947 info.append("ANR in ").append(app.processName);
2948 if (activity != null && activity.shortComponentName != null) {
2949 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002950 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08002951 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002952 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002953 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002954 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002955 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08002956 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002957 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002958
Dianne Hackborn287952c2010-09-22 22:34:31 -07002959 final ProcessStats processStats = new ProcessStats(true);
2960
2961 File tracesFile = dumpStackTraces(true, firstPids, processStats, lastPids);
2962
Dan Egnor42471dd2010-01-07 17:25:22 -08002963 String cpuInfo = null;
2964 if (MONITOR_CPU_USAGE) {
2965 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002966 synchronized (mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002967 cpuInfo = mProcessStats.printCurrentState(anrTime);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002968 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002969 info.append(processStats.printCurrentLoad());
Dan Egnor42471dd2010-01-07 17:25:22 -08002970 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002971 }
2972
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002973 info.append(processStats.printCurrentState(anrTime));
2974
Joe Onorato8a9b2202010-02-26 18:56:32 -08002975 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08002976 if (tracesFile == null) {
2977 // There is no trace file, so dump (only) the alleged culprit's threads to the log
2978 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
2979 }
2980
2981 addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
2982
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002983 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002984 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08002985 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
2986 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002987 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002988 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
2989 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002990 }
2991 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002992 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002993 }
2994 }
2995
Dan Egnor42471dd2010-01-07 17:25:22 -08002996 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
2997 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
2998 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07002999
3000 synchronized (this) {
3001 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07003002 Slog.w(TAG, "Killing " + app + ": background ANR");
3003 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
3004 app.processName, app.setAdj, "background ANR");
3005 Process.killProcessQuiet(app.pid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003006 return;
3007 }
3008
3009 // Set the app's notResponding state, and look up the errorReportReceiver
3010 makeAppNotRespondingLocked(app,
3011 activity != null ? activity.shortComponentName : null,
3012 annotation != null ? "ANR " + annotation : "ANR",
3013 info.toString());
3014
3015 // Bring up the infamous App Not Responding dialog
3016 Message msg = Message.obtain();
3017 HashMap map = new HashMap();
3018 msg.what = SHOW_NOT_RESPONDING_MSG;
3019 msg.obj = map;
3020 map.put("app", app);
3021 if (activity != null) {
3022 map.put("activity", activity);
3023 }
3024
3025 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08003026 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003027 }
3028
Dianne Hackborn0dad3642010-09-09 21:25:35 -07003029 final void showLaunchWarningLocked(final ActivityRecord cur, final ActivityRecord next) {
3030 if (!mLaunchWarningShown) {
3031 mLaunchWarningShown = true;
3032 mHandler.post(new Runnable() {
3033 @Override
3034 public void run() {
3035 synchronized (ActivityManagerService.this) {
3036 final Dialog d = new LaunchWarningWindow(mContext, cur, next);
3037 d.show();
3038 mHandler.postDelayed(new Runnable() {
3039 @Override
3040 public void run() {
3041 synchronized (ActivityManagerService.this) {
3042 d.dismiss();
3043 mLaunchWarningShown = false;
3044 }
3045 }
3046 }, 4000);
3047 }
3048 }
3049 });
3050 }
3051 }
3052
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003053 public boolean clearApplicationUserData(final String packageName,
3054 final IPackageDataObserver observer) {
3055 int uid = Binder.getCallingUid();
3056 int pid = Binder.getCallingPid();
3057 long callingId = Binder.clearCallingIdentity();
3058 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003059 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003060 int pkgUid = -1;
3061 synchronized(this) {
3062 try {
3063 pkgUid = pm.getPackageUid(packageName);
3064 } catch (RemoteException e) {
3065 }
3066 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003067 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003068 return false;
3069 }
3070 if (uid == pkgUid || checkComponentPermission(
3071 android.Manifest.permission.CLEAR_APP_USER_DATA,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08003072 pid, uid, -1, true)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003073 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003074 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003075 } else {
3076 throw new SecurityException(pid+" does not have permission:"+
3077 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
3078 "for process:"+packageName);
3079 }
3080 }
3081
3082 try {
3083 //clear application user data
3084 pm.clearApplicationUserData(packageName, observer);
3085 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
3086 Uri.fromParts("package", packageName, null));
3087 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003088 broadcastIntentInPackage("android", Process.SYSTEM_UID, intent,
3089 null, null, 0, null, null, null, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003090 } catch (RemoteException e) {
3091 }
3092 } finally {
3093 Binder.restoreCallingIdentity(callingId);
3094 }
3095 return true;
3096 }
3097
Dianne Hackborn03abb812010-01-04 18:43:19 -08003098 public void killBackgroundProcesses(final String packageName) {
3099 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
3100 != PackageManager.PERMISSION_GRANTED &&
3101 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
3102 != PackageManager.PERMISSION_GRANTED) {
3103 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003104 + Binder.getCallingPid()
3105 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08003106 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003107 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003108 throw new SecurityException(msg);
3109 }
3110
3111 long callingId = Binder.clearCallingIdentity();
3112 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003113 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003114 int pkgUid = -1;
3115 synchronized(this) {
3116 try {
3117 pkgUid = pm.getPackageUid(packageName);
3118 } catch (RemoteException e) {
3119 }
3120 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003121 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003122 return;
3123 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003124 killPackageProcessesLocked(packageName, pkgUid,
Christopher Tate3dacd842011-08-19 14:56:15 -07003125 ProcessList.SECONDARY_SERVER_ADJ, false, true, true, false);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003126 }
3127 } finally {
3128 Binder.restoreCallingIdentity(callingId);
3129 }
3130 }
3131
3132 public void forceStopPackage(final String packageName) {
3133 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
3134 != PackageManager.PERMISSION_GRANTED) {
3135 String msg = "Permission Denial: forceStopPackage() from pid="
3136 + Binder.getCallingPid()
3137 + ", uid=" + Binder.getCallingUid()
3138 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003139 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003140 throw new SecurityException(msg);
3141 }
3142
3143 long callingId = Binder.clearCallingIdentity();
3144 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003145 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn03abb812010-01-04 18:43:19 -08003146 int pkgUid = -1;
3147 synchronized(this) {
3148 try {
3149 pkgUid = pm.getPackageUid(packageName);
3150 } catch (RemoteException e) {
3151 }
3152 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003153 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003154 return;
3155 }
3156 forceStopPackageLocked(packageName, pkgUid);
Dianne Hackborne7f97212011-02-24 14:40:20 -08003157 try {
3158 pm.setPackageStoppedState(packageName, true);
3159 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08003160 } catch (IllegalArgumentException e) {
3161 Slog.w(TAG, "Failed trying to unstop package "
3162 + packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08003163 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003164 }
3165 } finally {
3166 Binder.restoreCallingIdentity(callingId);
3167 }
3168 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003169
3170 /*
3171 * The pkg name and uid have to be specified.
3172 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
3173 */
3174 public void killApplicationWithUid(String pkg, int uid) {
3175 if (pkg == null) {
3176 return;
3177 }
3178 // Make sure the uid is valid.
3179 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003180 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003181 return;
3182 }
3183 int callerUid = Binder.getCallingUid();
3184 // Only the system server can kill an application
3185 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07003186 // Post an aysnc message to kill the application
3187 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
3188 msg.arg1 = uid;
3189 msg.arg2 = 0;
3190 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07003191 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003192 } else {
3193 throw new SecurityException(callerUid + " cannot kill pkg: " +
3194 pkg);
3195 }
3196 }
3197
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003198 public void closeSystemDialogs(String reason) {
3199 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003200 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003201 if (reason != null) {
3202 intent.putExtra("reason", reason);
3203 }
3204
3205 final int uid = Binder.getCallingUid();
3206 final long origId = Binder.clearCallingIdentity();
3207 synchronized (this) {
3208 int i = mWatchers.beginBroadcast();
3209 while (i > 0) {
3210 i--;
3211 IActivityWatcher w = mWatchers.getBroadcastItem(i);
3212 if (w != null) {
3213 try {
3214 w.closingSystemDialogs(reason);
3215 } catch (RemoteException e) {
3216 }
3217 }
3218 }
3219 mWatchers.finishBroadcast();
3220
Dianne Hackbornffa42482009-09-23 22:20:11 -07003221 mWindowManager.closeSystemDialogs(reason);
3222
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003223 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3224 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackbornffa42482009-09-23 22:20:11 -07003225 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003226 r.stack.finishActivityLocked(r, i,
Dianne Hackbornffa42482009-09-23 22:20:11 -07003227 Activity.RESULT_CANCELED, null, "close-sys");
3228 }
3229 }
3230
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003231 broadcastIntentLocked(null, null, intent, null,
3232 null, 0, null, null, null, false, false, -1, uid);
3233 }
3234 Binder.restoreCallingIdentity(origId);
3235 }
3236
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003237 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003238 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003239 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
3240 for (int i=pids.length-1; i>=0; i--) {
3241 infos[i] = new Debug.MemoryInfo();
3242 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003243 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003244 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003245 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07003246
Dianne Hackbornb437e092011-08-05 17:50:29 -07003247 public long[] getProcessPss(int[] pids) throws RemoteException {
3248 long[] pss = new long[pids.length];
3249 for (int i=pids.length-1; i>=0; i--) {
3250 pss[i] = Debug.getPss(pids[i]);
3251 }
3252 return pss;
3253 }
3254
Christopher Tate5e1ab332009-09-01 20:32:49 -07003255 public void killApplicationProcess(String processName, int uid) {
3256 if (processName == null) {
3257 return;
3258 }
3259
3260 int callerUid = Binder.getCallingUid();
3261 // Only the system server can kill an application
3262 if (callerUid == Process.SYSTEM_UID) {
3263 synchronized (this) {
3264 ProcessRecord app = getProcessRecordLocked(processName, uid);
Christopher Tate4a627c72011-04-01 14:43:32 -07003265 if (app != null && app.thread != null) {
Christopher Tate5e1ab332009-09-01 20:32:49 -07003266 try {
3267 app.thread.scheduleSuicide();
3268 } catch (RemoteException e) {
3269 // If the other end already died, then our work here is done.
3270 }
3271 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003272 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07003273 + processName + " / " + uid);
3274 }
3275 }
3276 } else {
3277 throw new SecurityException(callerUid + " cannot kill app process: " +
3278 processName);
3279 }
3280 }
3281
Dianne Hackborn03abb812010-01-04 18:43:19 -08003282 private void forceStopPackageLocked(final String packageName, int uid) {
Christopher Tate3dacd842011-08-19 14:56:15 -07003283 forceStopPackageLocked(packageName, uid, false, false, true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003284 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
3285 Uri.fromParts("package", packageName, null));
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003286 if (!mProcessesReady) {
3287 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
3288 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003289 intent.putExtra(Intent.EXTRA_UID, uid);
3290 broadcastIntentLocked(null, null, intent,
3291 null, null, 0, null, null, null,
3292 false, false, MY_PID, Process.SYSTEM_UID);
3293 }
3294
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003295 private final boolean killPackageProcessesLocked(String packageName, int uid,
Christopher Tate3dacd842011-08-19 14:56:15 -07003296 int minOomAdj, boolean callerWillRestart, boolean allowRestart, boolean doit,
3297 boolean evenPersistent) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003298 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003299
Dianne Hackborn03abb812010-01-04 18:43:19 -08003300 // Remove all processes this package may have touched: all with the
3301 // same UID (except for the system or root user), and all whose name
3302 // matches the package name.
3303 final String procNamePrefix = packageName + ":";
3304 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
3305 final int NA = apps.size();
3306 for (int ia=0; ia<NA; ia++) {
3307 ProcessRecord app = apps.valueAt(ia);
Christopher Tate3dacd842011-08-19 14:56:15 -07003308 if (app.persistent && !evenPersistent) {
Christopher Tate064d8422011-07-26 15:38:07 -07003309 // we don't kill persistent processes
3310 continue;
3311 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003312 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003313 if (doit) {
3314 procs.add(app);
3315 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003316 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
3317 || app.processName.equals(packageName)
3318 || app.processName.startsWith(procNamePrefix)) {
3319 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003320 if (!doit) {
3321 return true;
3322 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003323 app.removed = true;
3324 procs.add(app);
3325 }
3326 }
3327 }
3328 }
3329
3330 int N = procs.size();
3331 for (int i=0; i<N; i++) {
Dianne Hackborn130b0d22011-07-26 22:07:48 -07003332 removeProcessLocked(procs.get(i), callerWillRestart, allowRestart);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003333 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003334 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08003335 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003336
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003337 private final boolean forceStopPackageLocked(String name, int uid,
Christopher Tate3dacd842011-08-19 14:56:15 -07003338 boolean callerWillRestart, boolean purgeCache, boolean doit,
3339 boolean evenPersistent) {
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07003340 int i;
3341 int N;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003342
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003343 if (uid < 0) {
3344 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003345 uid = AppGlobals.getPackageManager().getPackageUid(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003346 } catch (RemoteException e) {
3347 }
3348 }
3349
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003350 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003351 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003352
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003353 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
3354 while (badApps.hasNext()) {
3355 SparseArray<Long> ba = badApps.next();
3356 if (ba.get(uid) != null) {
3357 badApps.remove();
3358 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003359 }
3360 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003361
3362 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
Christopher Tate3dacd842011-08-19 14:56:15 -07003363 callerWillRestart, false, doit, evenPersistent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003364
Dianne Hackborne5ba16a2011-09-09 12:35:29 -07003365 TaskRecord lastTask = null;
3366 for (i=0; i<mMainStack.mHistory.size(); i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003367 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackborne5ba16a2011-09-09 12:35:29 -07003368 final boolean samePackage = r.packageName.equals(name);
3369 if ((samePackage || r.task == lastTask)
Christopher Tate3dacd842011-08-19 14:56:15 -07003370 && (r.app == null || evenPersistent || !r.app.persistent)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003371 if (!doit) {
Dianne Hackborn80a7ac12011-09-22 18:32:52 -07003372 if (r.finishing) {
3373 // If this activity is just finishing, then it is not
3374 // interesting as far as something to stop.
3375 continue;
3376 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003377 return true;
3378 }
3379 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003380 Slog.i(TAG, " Force finishing activity " + r);
Dianne Hackborne5ba16a2011-09-09 12:35:29 -07003381 if (samePackage) {
3382 if (r.app != null) {
3383 r.app.removed = true;
3384 }
3385 r.app = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003386 }
Dianne Hackborne5ba16a2011-09-09 12:35:29 -07003387 lastTask = r.task;
3388 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
3389 null, "force-stop")) {
3390 i--;
3391 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003392 }
3393 }
3394
3395 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
3396 for (ServiceRecord service : mServices.values()) {
Christopher Tate064d8422011-07-26 15:38:07 -07003397 if (service.packageName.equals(name)
Christopher Tate3dacd842011-08-19 14:56:15 -07003398 && (service.app == null || evenPersistent || !service.app.persistent)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003399 if (!doit) {
3400 return true;
3401 }
3402 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003403 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003404 if (service.app != null) {
3405 service.app.removed = true;
3406 }
3407 service.app = null;
3408 services.add(service);
3409 }
3410 }
3411
3412 N = services.size();
3413 for (i=0; i<N; i++) {
3414 bringDownServiceLocked(services.get(i), true);
3415 }
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07003416
3417 ArrayList<ContentProviderRecord> providers = new ArrayList<ContentProviderRecord>();
3418 for (ContentProviderRecord provider : mProvidersByClass.values()) {
3419 if (provider.info.packageName.equals(name)
3420 && (provider.proc == null || evenPersistent || !provider.proc.persistent)) {
3421 if (!doit) {
3422 return true;
3423 }
3424 didSomething = true;
3425 providers.add(provider);
3426 }
3427 }
3428
3429 N = providers.size();
3430 for (i=0; i<N; i++) {
3431 removeDyingProviderLocked(null, providers.get(i));
3432 }
3433
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003434 if (doit) {
3435 if (purgeCache) {
3436 AttributeCache ac = AttributeCache.instance();
3437 if (ac != null) {
3438 ac.removePackage(name);
3439 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003440 }
Dianne Hackborn38cc8962011-10-13 11:33:55 -07003441 if (mBooted) {
3442 mMainStack.resumeTopActivityLocked(null);
3443 mMainStack.scheduleIdleLocked();
3444 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003445 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003446
3447 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003448 }
3449
Dianne Hackborn130b0d22011-07-26 22:07:48 -07003450 private final boolean removeProcessLocked(ProcessRecord app,
3451 boolean callerWillRestart, boolean allowRestart) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003452 final String name = app.processName;
3453 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003454 if (DEBUG_PROCESSES) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003455 TAG, "Force removing process " + app + " (" + name
3456 + "/" + uid + ")");
3457
3458 mProcessNames.remove(name, uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003459 if (mHeavyWeightProcess == app) {
3460 mHeavyWeightProcess = null;
3461 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3462 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003463 boolean needRestart = false;
3464 if (app.pid > 0 && app.pid != MY_PID) {
3465 int pid = app.pid;
3466 synchronized (mPidsSelfLocked) {
3467 mPidsSelfLocked.remove(pid);
3468 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3469 }
Dianne Hackborn130b0d22011-07-26 22:07:48 -07003470 handleAppDiedLocked(app, true, allowRestart);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003471 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003472 Process.killProcess(pid);
3473
3474 if (app.persistent) {
3475 if (!callerWillRestart) {
3476 addAppLocked(app.info);
3477 } else {
3478 needRestart = true;
3479 }
3480 }
3481 } else {
3482 mRemovedProcesses.add(app);
3483 }
3484
3485 return needRestart;
3486 }
3487
3488 private final void processStartTimedOutLocked(ProcessRecord app) {
3489 final int pid = app.pid;
3490 boolean gone = false;
3491 synchronized (mPidsSelfLocked) {
3492 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
3493 if (knownApp != null && knownApp.thread == null) {
3494 mPidsSelfLocked.remove(pid);
3495 gone = true;
3496 }
3497 }
3498
3499 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003500 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003501 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003502 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003503 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003504 if (mHeavyWeightProcess == app) {
3505 mHeavyWeightProcess = null;
3506 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3507 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003508 // Take care of any launching providers waiting for this process.
3509 checkAppInLaunchingProvidersLocked(app, true);
3510 // Take care of any services that are waiting for the process.
3511 for (int i=0; i<mPendingServices.size(); i++) {
3512 ServiceRecord sr = mPendingServices.get(i);
3513 if (app.info.uid == sr.appInfo.uid
3514 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003515 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003516 mPendingServices.remove(i);
3517 i--;
3518 bringDownServiceLocked(sr, true);
3519 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003520 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07003521 EventLog.writeEvent(EventLogTags.AM_KILL, pid,
3522 app.processName, app.setAdj, "start timeout");
3523 Process.killProcessQuiet(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07003524 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003525 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07003526 try {
3527 IBackupManager bm = IBackupManager.Stub.asInterface(
3528 ServiceManager.getService(Context.BACKUP_SERVICE));
3529 bm.agentDisconnected(app.info.packageName);
3530 } catch (RemoteException e) {
3531 // Can't happen; the backup manager is local
3532 }
3533 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003534 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003535 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003536 mPendingBroadcast.state = BroadcastRecord.IDLE;
3537 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003538 mPendingBroadcast = null;
3539 scheduleBroadcastsLocked();
3540 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003541 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003542 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003543 }
3544 }
3545
3546 private final boolean attachApplicationLocked(IApplicationThread thread,
3547 int pid) {
3548
3549 // Find the application record that is being attached... either via
3550 // the pid if we are running in multiple processes, or just pull the
3551 // next app record if we are emulating process with anonymous threads.
3552 ProcessRecord app;
3553 if (pid != MY_PID && pid >= 0) {
3554 synchronized (mPidsSelfLocked) {
3555 app = mPidsSelfLocked.get(pid);
3556 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003557 } else {
3558 app = null;
3559 }
3560
3561 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003562 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003563 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003564 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003565 if (pid > 0 && pid != MY_PID) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07003566 Process.killProcessQuiet(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003567 } else {
3568 try {
3569 thread.scheduleExit();
3570 } catch (Exception e) {
3571 // Ignore exceptions.
3572 }
3573 }
3574 return false;
3575 }
3576
3577 // If this application record is still attached to a previous
3578 // process, clean it up now.
3579 if (app.thread != null) {
Dianne Hackborn130b0d22011-07-26 22:07:48 -07003580 handleAppDiedLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003581 }
3582
3583 // Tell the process all about itself.
3584
Joe Onorato8a9b2202010-02-26 18:56:32 -08003585 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003586 TAG, "Binding process pid " + pid + " to record " + app);
3587
3588 String processName = app.processName;
3589 try {
Dianne Hackborn1b64e0d2011-07-17 15:23:59 -07003590 AppDeathRecipient adr = new AppDeathRecipient(
3591 app, pid, thread);
3592 thread.asBinder().linkToDeath(adr, 0);
3593 app.deathRecipient = adr;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003594 } catch (RemoteException e) {
3595 app.resetPackageList();
3596 startProcessLocked(app, "link fail", processName);
3597 return false;
3598 }
3599
Doug Zongker2bec3d42009-12-04 12:52:44 -08003600 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003601
3602 app.thread = thread;
3603 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08003604 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
3605 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003606 app.forcingToForeground = null;
3607 app.foregroundServices = false;
Dianne Hackbornf0754f5b2011-07-21 16:02:07 -07003608 app.hasShownUi = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003609 app.debugging = false;
3610
3611 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3612
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003613 boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003614 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003615
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003616 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003617 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003618 }
3619
Joe Onorato8a9b2202010-02-26 18:56:32 -08003620 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003621 TAG, "New app record " + app
3622 + " thread=" + thread.asBinder() + " pid=" + pid);
3623 try {
3624 int testMode = IApplicationThread.DEBUG_OFF;
3625 if (mDebugApp != null && mDebugApp.equals(processName)) {
3626 testMode = mWaitForDebugger
3627 ? IApplicationThread.DEBUG_WAIT
3628 : IApplicationThread.DEBUG_ON;
3629 app.debugging = true;
3630 if (mDebugTransient) {
3631 mDebugApp = mOrigDebugApp;
3632 mWaitForDebugger = mOrigWaitForDebugger;
3633 }
3634 }
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07003635 String profileFile = app.instrumentationProfileFile;
3636 ParcelFileDescriptor profileFd = null;
3637 boolean profileAutoStop = false;
3638 if (mProfileApp != null && mProfileApp.equals(processName)) {
3639 mProfileProc = app;
3640 profileFile = mProfileFile;
3641 profileFd = mProfileFd;
3642 profileAutoStop = mAutoStopProfiler;
3643 }
3644
Christopher Tate181fafa2009-05-14 11:12:14 -07003645 // If the app is being launched for restore or full backup, set it up specially
3646 boolean isRestrictedBackupMode = false;
3647 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
3648 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
Christopher Tate75a99702011-05-18 16:28:19 -07003649 || (mBackupTarget.backupMode == BackupRecord.RESTORE_FULL)
Christopher Tate181fafa2009-05-14 11:12:14 -07003650 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
3651 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003652
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07003653 ensurePackageDexOpt(app.instrumentationInfo != null
3654 ? app.instrumentationInfo.packageName
3655 : app.info.packageName);
3656 if (app.instrumentationClass != null) {
3657 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003658 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003659 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003660 + processName + " with config " + mConfiguration);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04003661 ApplicationInfo appInfo = app.instrumentationInfo != null
3662 ? app.instrumentationInfo : app.info;
Dianne Hackborn8ea5e1d2011-05-27 16:45:31 -07003663 app.compat = compatibilityInfoForPackageLocked(appInfo);
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07003664 if (profileFd != null) {
3665 profileFd = profileFd.dup();
3666 }
Dianne Hackborne2515ee2011-04-27 18:52:56 -04003667 thread.bindApplication(processName, appInfo, providers,
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07003668 app.instrumentationClass, profileFile, profileFd, profileAutoStop,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003669 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn5d927c22011-09-02 12:22:18 -07003670 isRestrictedBackupMode || !normalMode, app.persistent,
Dianne Hackborn8ea5e1d2011-05-27 16:45:31 -07003671 mConfiguration, app.compat, getCommonServicesLocked(),
Svetoslav Ganov54d068e2011-03-02 12:58:40 -08003672 mCoreSettingsObserver.getCoreSettingsLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003673 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003674 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003675 } catch (Exception e) {
3676 // todo: Yikes! What should we do? For now we will try to
3677 // start another process, but that could easily get us in
3678 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08003679 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003680
3681 app.resetPackageList();
Dianne Hackborn1b64e0d2011-07-17 15:23:59 -07003682 app.unlinkDeathRecipient();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003683 startProcessLocked(app, "bind fail", processName);
3684 return false;
3685 }
3686
3687 // Remove this record from the list of starting applications.
3688 mPersistentStartingProcesses.remove(app);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003689 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
3690 "Attach application locked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003691 mProcessesOnHold.remove(app);
3692
3693 boolean badApp = false;
3694 boolean didSomething = false;
3695
3696 // See if the top visible activity is waiting to run in this process...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003697 ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07003698 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003699 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
3700 && processName.equals(hr.processName)) {
3701 try {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003702 if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003703 didSomething = true;
3704 }
3705 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003706 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003707 + hr.intent.getComponent().flattenToShortString(), e);
3708 badApp = true;
3709 }
3710 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003711 mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003712 }
3713 }
3714
3715 // Find any services that should be running in this process...
3716 if (!badApp && mPendingServices.size() > 0) {
3717 ServiceRecord sr = null;
3718 try {
3719 for (int i=0; i<mPendingServices.size(); i++) {
3720 sr = mPendingServices.get(i);
3721 if (app.info.uid != sr.appInfo.uid
3722 || !processName.equals(sr.processName)) {
3723 continue;
3724 }
3725
3726 mPendingServices.remove(i);
3727 i--;
3728 realStartServiceLocked(sr, app);
3729 didSomething = true;
3730 }
3731 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003732 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003733 + sr.shortName, e);
3734 badApp = true;
3735 }
3736 }
3737
3738 // Check if the next broadcast receiver is in this process...
3739 BroadcastRecord br = mPendingBroadcast;
3740 if (!badApp && br != null && br.curApp == app) {
3741 try {
3742 mPendingBroadcast = null;
3743 processCurBroadcastLocked(br, app);
3744 didSomething = true;
3745 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003746 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003747 + br.curComponent.flattenToShortString(), e);
3748 badApp = true;
Jeff Brown4d94a762010-09-23 11:33:28 -07003749 logBroadcastReceiverDiscardLocked(br);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003750 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
3751 br.resultExtras, br.resultAbort, true);
3752 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01003753 // We need to reset the state if we fails to start the receiver.
3754 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003755 }
3756 }
3757
Christopher Tate181fafa2009-05-14 11:12:14 -07003758 // Check whether the next backup agent is in this process...
3759 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003760 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003761 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07003762 try {
Dianne Hackborne2515ee2011-04-27 18:52:56 -04003763 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo,
3764 compatibilityInfoForPackageLocked(mBackupTarget.appInfo),
3765 mBackupTarget.backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -07003766 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003767 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07003768 e.printStackTrace();
3769 }
3770 }
3771
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003772 if (badApp) {
3773 // todo: Also need to kill application to deal with all
3774 // kinds of exceptions.
Dianne Hackborn130b0d22011-07-26 22:07:48 -07003775 handleAppDiedLocked(app, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003776 return false;
3777 }
3778
3779 if (!didSomething) {
3780 updateOomAdjLocked();
3781 }
3782
3783 return true;
3784 }
3785
3786 public final void attachApplication(IApplicationThread thread) {
3787 synchronized (this) {
3788 int callingPid = Binder.getCallingPid();
3789 final long origId = Binder.clearCallingIdentity();
3790 attachApplicationLocked(thread, callingPid);
3791 Binder.restoreCallingIdentity(origId);
3792 }
3793 }
3794
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07003795 public final void activityIdle(IBinder token, Configuration config, boolean stopProfiling) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003796 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07003797 ActivityRecord r = mMainStack.activityIdleInternal(token, false, config);
3798 if (stopProfiling) {
3799 synchronized (this) {
3800 if (mProfileProc == r.app) {
3801 if (mProfileFd != null) {
3802 try {
3803 mProfileFd.close();
3804 } catch (IOException e) {
3805 }
3806 clearProfilerLocked();
3807 }
3808 }
3809 }
3810 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003811 Binder.restoreCallingIdentity(origId);
3812 }
3813
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003814 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003815 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003816 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003817 mWindowManager.enableScreenAfterBoot();
3818 }
3819
Dianne Hackborn661cd522011-08-22 00:26:20 -07003820 public void showBootMessage(final CharSequence msg, final boolean always) {
3821 mWindowManager.showBootMessage(msg, always);
3822 }
3823
Dianne Hackborn90c52de2011-09-23 12:57:44 -07003824 public void dismissKeyguardOnNextActivity() {
3825 synchronized (this) {
3826 mMainStack.dismissKeyguardOnNextActivityLocked();
3827 }
3828 }
3829
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003830 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003831 IntentFilter pkgFilter = new IntentFilter();
3832 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
3833 pkgFilter.addDataScheme("package");
3834 mContext.registerReceiver(new BroadcastReceiver() {
3835 @Override
3836 public void onReceive(Context context, Intent intent) {
3837 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
3838 if (pkgs != null) {
3839 for (String pkg : pkgs) {
Vairavan Srinivasan61f07652010-07-22 13:36:40 -07003840 synchronized (ActivityManagerService.this) {
Christopher Tate3dacd842011-08-19 14:56:15 -07003841 if (forceStopPackageLocked(pkg, -1, false, false, false, false)) {
Vairavan Srinivasan61f07652010-07-22 13:36:40 -07003842 setResultCode(Activity.RESULT_OK);
3843 return;
3844 }
3845 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003846 }
3847 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003848 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003849 }, pkgFilter);
3850
3851 synchronized (this) {
3852 // Ensure that any processes we had put on hold are now started
3853 // up.
3854 final int NP = mProcessesOnHold.size();
3855 if (NP > 0) {
3856 ArrayList<ProcessRecord> procs =
3857 new ArrayList<ProcessRecord>(mProcessesOnHold);
3858 for (int ip=0; ip<NP; ip++) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003859 if (DEBUG_PROCESSES) Slog.v(TAG, "Starting process on hold: "
3860 + procs.get(ip));
3861 startProcessLocked(procs.get(ip), "on-hold", null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003862 }
3863 }
3864
3865 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07003866 // Start looking for apps that are abusing wake locks.
3867 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07003868 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003869 // Tell anyone interested that we are done booting!
Dianne Hackbornf4c454b2010-08-11 12:47:41 -07003870 SystemProperties.set("sys.boot_completed", "1");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003871 broadcastIntentLocked(null, null,
3872 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
3873 null, null, 0, null, null,
3874 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
3875 false, false, MY_PID, Process.SYSTEM_UID);
3876 }
3877 }
3878 }
3879
3880 final void ensureBootCompleted() {
3881 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003882 boolean enableScreen;
3883 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003884 booting = mBooting;
3885 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003886 enableScreen = !mBooted;
3887 mBooted = true;
3888 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003889
3890 if (booting) {
3891 finishBooting();
3892 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003893
3894 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07003895 enableScreenAfterBoot();
3896 }
3897 }
3898
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08003899 public final void activityPaused(IBinder token) {
3900 final long origId = Binder.clearCallingIdentity();
3901 mMainStack.activityPaused(token, false);
3902 Binder.restoreCallingIdentity(origId);
3903 }
3904
3905 public final void activityStopped(IBinder token, Bundle icicle, Bitmap thumbnail,
3906 CharSequence description) {
3907 if (localLOGV) Slog.v(
3908 TAG, "Activity stopped: token=" + token);
3909
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003910 // Refuse possible leaked file descriptors
3911 if (icicle != null && icicle.hasFileDescriptors()) {
3912 throw new IllegalArgumentException("File descriptors passed in Bundle");
3913 }
3914
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003915 ActivityRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003916
3917 final long origId = Binder.clearCallingIdentity();
3918
3919 synchronized (this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07003920 r = mMainStack.isInStackLocked(token);
3921 if (r != null) {
3922 r.stack.activityStoppedLocked(r, icicle, thumbnail, description);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003923 }
3924 }
3925
3926 if (r != null) {
3927 sendPendingThumbnail(r, null, null, null, false);
3928 }
3929
3930 trimApplications();
3931
3932 Binder.restoreCallingIdentity(origId);
3933 }
3934
3935 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003936 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003937 mMainStack.activityDestroyed(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003938 }
3939
3940 public String getCallingPackage(IBinder token) {
3941 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003942 ActivityRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07003943 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003944 }
3945 }
3946
3947 public ComponentName getCallingActivity(IBinder token) {
3948 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003949 ActivityRecord r = getCallingRecordLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003950 return r != null ? r.intent.getComponent() : null;
3951 }
3952 }
3953
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003954 private ActivityRecord getCallingRecordLocked(IBinder token) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07003955 ActivityRecord r = mMainStack.isInStackLocked(token);
3956 if (r == null) {
3957 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003958 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -07003959 return r.resultTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003960 }
3961
3962 public ComponentName getActivityClassForToken(IBinder token) {
3963 synchronized(this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07003964 ActivityRecord r = mMainStack.isInStackLocked(token);
3965 if (r == null) {
3966 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003967 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -07003968 return r.intent.getComponent();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003969 }
3970 }
3971
3972 public String getPackageForToken(IBinder token) {
3973 synchronized(this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07003974 ActivityRecord r = mMainStack.isInStackLocked(token);
3975 if (r == null) {
3976 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003977 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -07003978 return r.packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003979 }
3980 }
3981
3982 public IIntentSender getIntentSender(int type,
3983 String packageName, IBinder token, String resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003984 int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003985 // Refuse possible leaked file descriptors
Dianne Hackborn621e17d2010-11-22 15:59:56 -08003986 if (intents != null) {
3987 if (intents.length < 1) {
3988 throw new IllegalArgumentException("Intents array length must be >= 1");
3989 }
3990 for (int i=0; i<intents.length; i++) {
3991 Intent intent = intents[i];
Dianne Hackborn52b0ce02011-04-14 13:09:32 -07003992 if (intent != null) {
3993 if (intent.hasFileDescriptors()) {
3994 throw new IllegalArgumentException("File descriptors passed in Intent");
3995 }
3996 if (type == INTENT_SENDER_BROADCAST &&
3997 (intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
3998 throw new IllegalArgumentException(
3999 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
4000 }
4001 intents[i] = new Intent(intent);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004002 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004003 }
4004 if (resolvedTypes != null && resolvedTypes.length != intents.length) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07004005 throw new IllegalArgumentException(
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004006 "Intent array length does not match resolvedTypes length");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07004007 }
4008 }
4009
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004010 synchronized(this) {
4011 int callingUid = Binder.getCallingUid();
4012 try {
Jeff Brown10e89712011-07-08 18:52:57 -07004013 if (callingUid != 0 && callingUid != Process.SYSTEM_UID) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004014 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004015 .getPackageUid(packageName);
4016 if (uid != Binder.getCallingUid()) {
4017 String msg = "Permission Denial: getIntentSender() from pid="
4018 + Binder.getCallingPid()
4019 + ", uid=" + Binder.getCallingUid()
4020 + ", (need uid=" + uid + ")"
4021 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004022 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004023 throw new SecurityException(msg);
4024 }
4025 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004026
4027 return getIntentSenderLocked(type, packageName, callingUid,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004028 token, resultWho, requestCode, intents, resolvedTypes, flags);
Dianne Hackborn860755f2010-06-03 18:47:52 -07004029
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004030 } catch (RemoteException e) {
4031 throw new SecurityException(e);
4032 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004033 }
4034 }
4035
4036 IIntentSender getIntentSenderLocked(int type,
4037 String packageName, int callingUid, IBinder token, String resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004038 int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004039 ActivityRecord activity = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004040 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004041 activity = mMainStack.isInStackLocked(token);
4042 if (activity == null) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07004043 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004044 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004045 if (activity.finishing) {
4046 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004047 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004048 }
4049
4050 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
4051 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
4052 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
4053 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
4054 |PendingIntent.FLAG_UPDATE_CURRENT);
4055
4056 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
4057 type, packageName, activity, resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004058 requestCode, intents, resolvedTypes, flags);
Dianne Hackborn860755f2010-06-03 18:47:52 -07004059 WeakReference<PendingIntentRecord> ref;
4060 ref = mIntentSenderRecords.get(key);
4061 PendingIntentRecord rec = ref != null ? ref.get() : null;
4062 if (rec != null) {
4063 if (!cancelCurrent) {
4064 if (updateCurrent) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004065 if (rec.key.requestIntent != null) {
4066 rec.key.requestIntent.replaceExtras(intents != null ? intents[0] : null);
4067 }
4068 if (intents != null) {
4069 intents[intents.length-1] = rec.key.requestIntent;
4070 rec.key.allIntents = intents;
4071 rec.key.allResolvedTypes = resolvedTypes;
4072 } else {
4073 rec.key.allIntents = null;
4074 rec.key.allResolvedTypes = null;
4075 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004076 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004077 return rec;
4078 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004079 rec.canceled = true;
4080 mIntentSenderRecords.remove(key);
4081 }
4082 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004083 return rec;
4084 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004085 rec = new PendingIntentRecord(this, key, callingUid);
4086 mIntentSenderRecords.put(key, rec.ref);
4087 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
4088 if (activity.pendingResults == null) {
4089 activity.pendingResults
4090 = new HashSet<WeakReference<PendingIntentRecord>>();
4091 }
4092 activity.pendingResults.add(rec.ref);
4093 }
4094 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004095 }
4096
4097 public void cancelIntentSender(IIntentSender sender) {
4098 if (!(sender instanceof PendingIntentRecord)) {
4099 return;
4100 }
4101 synchronized(this) {
4102 PendingIntentRecord rec = (PendingIntentRecord)sender;
4103 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004104 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004105 .getPackageUid(rec.key.packageName);
4106 if (uid != Binder.getCallingUid()) {
4107 String msg = "Permission Denial: cancelIntentSender() from pid="
4108 + Binder.getCallingPid()
4109 + ", uid=" + Binder.getCallingUid()
4110 + " is not allowed to cancel packges "
4111 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004112 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004113 throw new SecurityException(msg);
4114 }
4115 } catch (RemoteException e) {
4116 throw new SecurityException(e);
4117 }
4118 cancelIntentSenderLocked(rec, true);
4119 }
4120 }
4121
4122 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
4123 rec.canceled = true;
4124 mIntentSenderRecords.remove(rec.key);
4125 if (cleanActivity && rec.key.activity != null) {
4126 rec.key.activity.pendingResults.remove(rec.ref);
4127 }
4128 }
4129
4130 public String getPackageForIntentSender(IIntentSender pendingResult) {
4131 if (!(pendingResult instanceof PendingIntentRecord)) {
4132 return null;
4133 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07004134 try {
4135 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
4136 return res.key.packageName;
4137 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004138 }
4139 return null;
4140 }
4141
Dianne Hackborn6c418d52011-06-29 14:05:33 -07004142 public boolean isIntentSenderTargetedToPackage(IIntentSender pendingResult) {
4143 if (!(pendingResult instanceof PendingIntentRecord)) {
4144 return false;
4145 }
4146 try {
4147 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
4148 if (res.key.allIntents == null) {
4149 return false;
4150 }
4151 for (int i=0; i<res.key.allIntents.length; i++) {
4152 Intent intent = res.key.allIntents[i];
4153 if (intent.getPackage() != null && intent.getComponent() != null) {
4154 return false;
4155 }
4156 }
4157 return true;
4158 } catch (ClassCastException e) {
4159 }
4160 return false;
4161 }
4162
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004163 public void setProcessLimit(int max) {
4164 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4165 "setProcessLimit()");
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004166 synchronized (this) {
Dianne Hackborn7d608422011-08-07 16:24:18 -07004167 mProcessLimit = max < 0 ? ProcessList.MAX_HIDDEN_APPS : max;
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004168 mProcessLimitOverride = max;
4169 }
4170 trimApplications();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004171 }
4172
4173 public int getProcessLimit() {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004174 synchronized (this) {
4175 return mProcessLimitOverride;
4176 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004177 }
4178
4179 void foregroundTokenDied(ForegroundToken token) {
4180 synchronized (ActivityManagerService.this) {
4181 synchronized (mPidsSelfLocked) {
4182 ForegroundToken cur
4183 = mForegroundProcesses.get(token.pid);
4184 if (cur != token) {
4185 return;
4186 }
4187 mForegroundProcesses.remove(token.pid);
4188 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
4189 if (pr == null) {
4190 return;
4191 }
4192 pr.forcingToForeground = null;
4193 pr.foregroundServices = false;
4194 }
4195 updateOomAdjLocked();
4196 }
4197 }
4198
4199 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
4200 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4201 "setProcessForeground()");
4202 synchronized(this) {
4203 boolean changed = false;
4204
4205 synchronized (mPidsSelfLocked) {
4206 ProcessRecord pr = mPidsSelfLocked.get(pid);
4207 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004208 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004209 return;
4210 }
4211 ForegroundToken oldToken = mForegroundProcesses.get(pid);
4212 if (oldToken != null) {
4213 oldToken.token.unlinkToDeath(oldToken, 0);
4214 mForegroundProcesses.remove(pid);
4215 pr.forcingToForeground = null;
4216 changed = true;
4217 }
4218 if (isForeground && token != null) {
4219 ForegroundToken newToken = new ForegroundToken() {
4220 public void binderDied() {
4221 foregroundTokenDied(this);
4222 }
4223 };
4224 newToken.pid = pid;
4225 newToken.token = token;
4226 try {
4227 token.linkToDeath(newToken, 0);
4228 mForegroundProcesses.put(pid, newToken);
4229 pr.forcingToForeground = token;
4230 changed = true;
4231 } catch (RemoteException e) {
4232 // If the process died while doing this, we will later
4233 // do the cleanup with the process death link.
4234 }
4235 }
4236 }
4237
4238 if (changed) {
4239 updateOomAdjLocked();
4240 }
4241 }
4242 }
4243
4244 // =========================================================
4245 // PERMISSIONS
4246 // =========================================================
4247
4248 static class PermissionController extends IPermissionController.Stub {
4249 ActivityManagerService mActivityManagerService;
4250 PermissionController(ActivityManagerService activityManagerService) {
4251 mActivityManagerService = activityManagerService;
4252 }
4253
4254 public boolean checkPermission(String permission, int pid, int uid) {
4255 return mActivityManagerService.checkPermission(permission, pid,
4256 uid) == PackageManager.PERMISSION_GRANTED;
4257 }
4258 }
4259
4260 /**
4261 * This can be called with or without the global lock held.
4262 */
4263 int checkComponentPermission(String permission, int pid, int uid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004264 int owningUid, boolean exported) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004265 // We might be performing an operation on behalf of an indirect binder
4266 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
4267 // client identity accordingly before proceeding.
4268 Identity tlsIdentity = sCallerIdentity.get();
4269 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004270 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004271 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
4272 uid = tlsIdentity.uid;
4273 pid = tlsIdentity.pid;
4274 }
4275
4276 // Root, system server and our own process get to do everything.
Jeff Brown10e89712011-07-08 18:52:57 -07004277 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004278 return PackageManager.PERMISSION_GRANTED;
4279 }
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004280 // If there is a uid that owns whatever is being accessed, it has
4281 // blanket access to it regardless of the permissions it requires.
4282 if (owningUid >= 0 && uid == owningUid) {
4283 return PackageManager.PERMISSION_GRANTED;
4284 }
4285 // If the target is not exported, then nobody else can get to it.
4286 if (!exported) {
4287 Slog.w(TAG, "Permission denied: checkComponentPermission() owningUid=" + owningUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004288 return PackageManager.PERMISSION_DENIED;
4289 }
4290 if (permission == null) {
4291 return PackageManager.PERMISSION_GRANTED;
4292 }
4293 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004294 return AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004295 .checkUidPermission(permission, uid);
4296 } catch (RemoteException e) {
4297 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004298 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004299 }
4300 return PackageManager.PERMISSION_DENIED;
4301 }
4302
4303 /**
4304 * As the only public entry point for permissions checking, this method
4305 * can enforce the semantic that requesting a check on a null global
4306 * permission is automatically denied. (Internally a null permission
4307 * string is used when calling {@link #checkComponentPermission} in cases
4308 * when only uid-based security is needed.)
4309 *
4310 * This can be called with or without the global lock held.
4311 */
4312 public int checkPermission(String permission, int pid, int uid) {
4313 if (permission == null) {
4314 return PackageManager.PERMISSION_DENIED;
4315 }
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004316 return checkComponentPermission(permission, pid, uid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004317 }
4318
4319 /**
4320 * Binder IPC calls go through the public entry point.
4321 * This can be called with or without the global lock held.
4322 */
4323 int checkCallingPermission(String permission) {
4324 return checkPermission(permission,
4325 Binder.getCallingPid(),
4326 Binder.getCallingUid());
4327 }
4328
4329 /**
4330 * This can be called with or without the global lock held.
4331 */
4332 void enforceCallingPermission(String permission, String func) {
4333 if (checkCallingPermission(permission)
4334 == PackageManager.PERMISSION_GRANTED) {
4335 return;
4336 }
4337
4338 String msg = "Permission Denial: " + func + " from pid="
4339 + Binder.getCallingPid()
4340 + ", uid=" + Binder.getCallingUid()
4341 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004342 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004343 throw new SecurityException(msg);
4344 }
4345
4346 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
Dianne Hackborn48058e82010-09-27 16:53:23 -07004347 ProviderInfo pi, Uri uri, int uid, int modeFlags) {
4348 boolean readPerm = (modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0;
4349 boolean writePerm = (modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0;
4350 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4351 "checkHoldingPermissionsLocked: uri=" + uri + " uid=" + uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004352 try {
Dianne Hackborn48058e82010-09-27 16:53:23 -07004353 // Is the component private from the target uid?
4354 final boolean prv = !pi.exported && pi.applicationInfo.uid != uid;
4355
4356 // Acceptable if the there is no read permission needed from the
4357 // target or the target is holding the read permission.
4358 if (!readPerm) {
4359 if ((!prv && pi.readPermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004360 (pm.checkUidPermission(pi.readPermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004361 == PackageManager.PERMISSION_GRANTED)) {
4362 readPerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004363 }
4364 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004365
4366 // Acceptable if the there is no write permission needed from the
4367 // target or the target is holding the read permission.
4368 if (!writePerm) {
4369 if (!prv && (pi.writePermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004370 (pm.checkUidPermission(pi.writePermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004371 == PackageManager.PERMISSION_GRANTED)) {
4372 writePerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004373 }
4374 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004375
4376 // Acceptable if there is a path permission matching the URI that
4377 // the target holds the permission on.
4378 PathPermission[] pps = pi.pathPermissions;
4379 if (pps != null && (!readPerm || !writePerm)) {
4380 final String path = uri.getPath();
4381 int i = pps.length;
4382 while (i > 0 && (!readPerm || !writePerm)) {
4383 i--;
4384 PathPermission pp = pps[i];
4385 if (!readPerm) {
4386 final String pprperm = pp.getReadPermission();
4387 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking read perm for "
4388 + pprperm + " for " + pp.getPath()
4389 + ": match=" + pp.match(path)
4390 + " check=" + pm.checkUidPermission(pprperm, uid));
4391 if (pprperm != null && pp.match(path) &&
4392 (pm.checkUidPermission(pprperm, uid)
4393 == PackageManager.PERMISSION_GRANTED)) {
4394 readPerm = true;
4395 }
4396 }
4397 if (!writePerm) {
4398 final String ppwperm = pp.getWritePermission();
4399 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking write perm "
4400 + ppwperm + " for " + pp.getPath()
4401 + ": match=" + pp.match(path)
4402 + " check=" + pm.checkUidPermission(ppwperm, uid));
4403 if (ppwperm != null && pp.match(path) &&
4404 (pm.checkUidPermission(ppwperm, uid)
4405 == PackageManager.PERMISSION_GRANTED)) {
4406 writePerm = true;
4407 }
4408 }
4409 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004410 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004411 } catch (RemoteException e) {
4412 return false;
4413 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004414
4415 return readPerm && writePerm;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004416 }
4417
4418 private final boolean checkUriPermissionLocked(Uri uri, int uid,
4419 int modeFlags) {
4420 // Root gets to do everything.
Jeff Brown10e89712011-07-08 18:52:57 -07004421 if (uid == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004422 return true;
4423 }
4424 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
4425 if (perms == null) return false;
4426 UriPermission perm = perms.get(uri);
4427 if (perm == null) return false;
4428 return (modeFlags&perm.modeFlags) == modeFlags;
4429 }
4430
4431 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
4432 // Another redirected-binder-call permissions check as in
4433 // {@link checkComponentPermission}.
4434 Identity tlsIdentity = sCallerIdentity.get();
4435 if (tlsIdentity != null) {
4436 uid = tlsIdentity.uid;
4437 pid = tlsIdentity.pid;
4438 }
4439
4440 // Our own process gets to do everything.
4441 if (pid == MY_PID) {
4442 return PackageManager.PERMISSION_GRANTED;
4443 }
4444 synchronized(this) {
4445 return checkUriPermissionLocked(uri, uid, modeFlags)
4446 ? PackageManager.PERMISSION_GRANTED
4447 : PackageManager.PERMISSION_DENIED;
4448 }
4449 }
4450
Dianne Hackborn39792d22010-08-19 18:01:52 -07004451 /**
4452 * Check if the targetPkg can be granted permission to access uri by
4453 * the callingUid using the given modeFlags. Throws a security exception
4454 * if callingUid is not allowed to do this. Returns the uid of the target
4455 * if the URI permission grant should be performed; returns -1 if it is not
4456 * needed (for example targetPkg already has permission to access the URI).
4457 */
4458 int checkGrantUriPermissionLocked(int callingUid, String targetPkg,
4459 Uri uri, int modeFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004460 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4461 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4462 if (modeFlags == 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004463 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004464 }
4465
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004466 if (targetPkg != null) {
4467 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4468 "Checking grant " + targetPkg + " permission to " + uri);
4469 }
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004470
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004471 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004472
4473 // If this is not a content: uri, we can't do anything with it.
4474 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004475 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004476 "Can't grant URI permission for non-content URI: " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004477 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004478 }
4479
4480 String name = uri.getAuthority();
4481 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004482 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004483 if (cpr != null) {
4484 pi = cpr.info;
4485 } else {
4486 try {
4487 pi = pm.resolveContentProvider(name,
4488 PackageManager.GET_URI_PERMISSION_PATTERNS);
4489 } catch (RemoteException ex) {
4490 }
4491 }
4492 if (pi == null) {
Dianne Hackborn98cfebc2011-10-18 13:17:33 -07004493 Slog.w(TAG, "No content provider found for permission check: " + uri.toSafeString());
Dianne Hackborn39792d22010-08-19 18:01:52 -07004494 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004495 }
4496
4497 int targetUid;
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004498 if (targetPkg != null) {
4499 try {
4500 targetUid = pm.getPackageUid(targetPkg);
4501 if (targetUid < 0) {
4502 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4503 "Can't grant URI permission no uid for: " + targetPkg);
4504 return -1;
4505 }
4506 } catch (RemoteException ex) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004507 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004508 }
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004509 } else {
4510 targetUid = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004511 }
4512
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004513 if (targetUid >= 0) {
4514 // First... does the target actually need this permission?
4515 if (checkHoldingPermissionsLocked(pm, pi, uri, targetUid, modeFlags)) {
4516 // No need to grant the target this permission.
4517 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4518 "Target " + targetPkg + " already has full permission to " + uri);
4519 return -1;
4520 }
4521 } else {
4522 // First... there is no target package, so can anyone access it?
4523 boolean allowed = pi.exported;
4524 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4525 if (pi.readPermission != null) {
4526 allowed = false;
4527 }
4528 }
4529 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4530 if (pi.writePermission != null) {
4531 allowed = false;
4532 }
4533 }
4534 if (allowed) {
4535 return -1;
4536 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004537 }
4538
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004539 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004540 if (!pi.grantUriPermissions) {
4541 throw new SecurityException("Provider " + pi.packageName
4542 + "/" + pi.name
4543 + " does not allow granting of Uri permissions (uri "
4544 + uri + ")");
4545 }
4546 if (pi.uriPermissionPatterns != null) {
4547 final int N = pi.uriPermissionPatterns.length;
4548 boolean allowed = false;
4549 for (int i=0; i<N; i++) {
4550 if (pi.uriPermissionPatterns[i] != null
4551 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
4552 allowed = true;
4553 break;
4554 }
4555 }
4556 if (!allowed) {
4557 throw new SecurityException("Provider " + pi.packageName
4558 + "/" + pi.name
4559 + " does not allow granting of permission to path of Uri "
4560 + uri);
4561 }
4562 }
4563
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004564 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004565 // this uri?
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004566 if (callingUid != Process.myUid()) {
4567 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
4568 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4569 throw new SecurityException("Uid " + callingUid
4570 + " does not have permission to uri " + uri);
4571 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004572 }
4573 }
4574
Dianne Hackborn39792d22010-08-19 18:01:52 -07004575 return targetUid;
4576 }
4577
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004578 public int checkGrantUriPermission(int callingUid, String targetPkg,
4579 Uri uri, int modeFlags) {
4580 synchronized(this) {
4581 return checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4582 }
4583 }
4584
Dianne Hackborn39792d22010-08-19 18:01:52 -07004585 void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg,
4586 Uri uri, int modeFlags, UriPermissionOwner owner) {
4587 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4588 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4589 if (modeFlags == 0) {
4590 return;
4591 }
4592
4593 // So here we are: the caller has the assumed permission
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004594 // to the uri, and the target doesn't. Let's now give this to
4595 // the target.
4596
Joe Onorato8a9b2202010-02-26 18:56:32 -08004597 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004598 "Granting " + targetPkg + "/" + targetUid + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004599
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004600 HashMap<Uri, UriPermission> targetUris
4601 = mGrantedUriPermissions.get(targetUid);
4602 if (targetUris == null) {
4603 targetUris = new HashMap<Uri, UriPermission>();
4604 mGrantedUriPermissions.put(targetUid, targetUris);
4605 }
4606
4607 UriPermission perm = targetUris.get(uri);
4608 if (perm == null) {
4609 perm = new UriPermission(targetUid, uri);
4610 targetUris.put(uri, perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004611 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004612
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004613 perm.modeFlags |= modeFlags;
Dianne Hackborn39792d22010-08-19 18:01:52 -07004614 if (owner == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004615 perm.globalModeFlags |= modeFlags;
Vairavan Srinivasan91c12c22011-01-21 18:26:06 -08004616 } else {
4617 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4618 perm.readOwners.add(owner);
4619 owner.addReadPermission(perm);
4620 }
4621 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4622 perm.writeOwners.add(owner);
4623 owner.addWritePermission(perm);
4624 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004625 }
4626 }
4627
Dianne Hackborn39792d22010-08-19 18:01:52 -07004628 void grantUriPermissionLocked(int callingUid,
4629 String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) {
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004630 if (targetPkg == null) {
4631 throw new NullPointerException("targetPkg");
4632 }
4633
Dianne Hackborn39792d22010-08-19 18:01:52 -07004634 int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4635 if (targetUid < 0) {
4636 return;
4637 }
4638
4639 grantUriPermissionUncheckedLocked(targetUid, targetPkg, uri, modeFlags, owner);
4640 }
4641
4642 /**
4643 * Like checkGrantUriPermissionLocked, but takes an Intent.
4644 */
4645 int checkGrantUriPermissionFromIntentLocked(int callingUid,
4646 String targetPkg, Intent intent) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07004647 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004648 "Checking URI perm to " + (intent != null ? intent.getData() : null)
Dianne Hackbornb424b632010-08-18 15:59:05 -07004649 + " from " + intent + "; flags=0x"
4650 + Integer.toHexString(intent != null ? intent.getFlags() : 0));
4651
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004652 if (targetPkg == null) {
4653 throw new NullPointerException("targetPkg");
4654 }
4655
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004656 if (intent == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004657 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004658 }
4659 Uri data = intent.getData();
4660 if (data == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004661 return -1;
4662 }
4663 return checkGrantUriPermissionLocked(callingUid, targetPkg, data,
4664 intent.getFlags());
4665 }
4666
4667 /**
4668 * Like grantUriPermissionUncheckedLocked, but takes an Intent.
4669 */
4670 void grantUriPermissionUncheckedFromIntentLocked(int targetUid,
4671 String targetPkg, Intent intent, UriPermissionOwner owner) {
4672 grantUriPermissionUncheckedLocked(targetUid, targetPkg, intent.getData(),
4673 intent.getFlags(), owner);
4674 }
4675
4676 void grantUriPermissionFromIntentLocked(int callingUid,
4677 String targetPkg, Intent intent, UriPermissionOwner owner) {
4678 int targetUid = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg, intent);
4679 if (targetUid < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004680 return;
4681 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07004682
4683 grantUriPermissionUncheckedFromIntentLocked(targetUid, targetPkg, intent, owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004684 }
4685
4686 public void grantUriPermission(IApplicationThread caller, String targetPkg,
4687 Uri uri, int modeFlags) {
4688 synchronized(this) {
4689 final ProcessRecord r = getRecordForAppLocked(caller);
4690 if (r == null) {
4691 throw new SecurityException("Unable to find app for caller "
4692 + caller
4693 + " when granting permission to uri " + uri);
4694 }
4695 if (targetPkg == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004696 throw new IllegalArgumentException("null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004697 }
4698 if (uri == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004699 throw new IllegalArgumentException("null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004700 }
4701
4702 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
4703 null);
4704 }
4705 }
4706
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004707 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004708 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
4709 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
4710 HashMap<Uri, UriPermission> perms
4711 = mGrantedUriPermissions.get(perm.uid);
4712 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004713 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004714 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004715 perms.remove(perm.uri);
4716 if (perms.size() == 0) {
4717 mGrantedUriPermissions.remove(perm.uid);
4718 }
4719 }
4720 }
4721 }
4722
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004723 private void revokeUriPermissionLocked(int callingUid, Uri uri,
4724 int modeFlags) {
4725 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4726 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4727 if (modeFlags == 0) {
4728 return;
4729 }
4730
Joe Onorato8a9b2202010-02-26 18:56:32 -08004731 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004732 "Revoking all granted permissions to " + uri);
4733
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004734 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004735
4736 final String authority = uri.getAuthority();
4737 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004738 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004739 if (cpr != null) {
4740 pi = cpr.info;
4741 } else {
4742 try {
4743 pi = pm.resolveContentProvider(authority,
4744 PackageManager.GET_URI_PERMISSION_PATTERNS);
4745 } catch (RemoteException ex) {
4746 }
4747 }
4748 if (pi == null) {
Dianne Hackborn98cfebc2011-10-18 13:17:33 -07004749 Slog.w(TAG, "No content provider found for permission revoke: " + uri.toSafeString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004750 return;
4751 }
4752
4753 // Does the caller have this permission on the URI?
Dianne Hackborn48058e82010-09-27 16:53:23 -07004754 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004755 // Right now, if you are not the original owner of the permission,
4756 // you are not allowed to revoke it.
4757 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4758 throw new SecurityException("Uid " + callingUid
4759 + " does not have permission to uri " + uri);
4760 //}
4761 }
4762
4763 // Go through all of the permissions and remove any that match.
4764 final List<String> SEGMENTS = uri.getPathSegments();
4765 if (SEGMENTS != null) {
4766 final int NS = SEGMENTS.size();
4767 int N = mGrantedUriPermissions.size();
4768 for (int i=0; i<N; i++) {
4769 HashMap<Uri, UriPermission> perms
4770 = mGrantedUriPermissions.valueAt(i);
4771 Iterator<UriPermission> it = perms.values().iterator();
4772 toploop:
4773 while (it.hasNext()) {
4774 UriPermission perm = it.next();
4775 Uri targetUri = perm.uri;
4776 if (!authority.equals(targetUri.getAuthority())) {
4777 continue;
4778 }
4779 List<String> targetSegments = targetUri.getPathSegments();
4780 if (targetSegments == null) {
4781 continue;
4782 }
4783 if (targetSegments.size() < NS) {
4784 continue;
4785 }
4786 for (int j=0; j<NS; j++) {
4787 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
4788 continue toploop;
4789 }
4790 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004791 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004792 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004793 perm.clearModes(modeFlags);
4794 if (perm.modeFlags == 0) {
4795 it.remove();
4796 }
4797 }
4798 if (perms.size() == 0) {
4799 mGrantedUriPermissions.remove(
4800 mGrantedUriPermissions.keyAt(i));
4801 N--;
4802 i--;
4803 }
4804 }
4805 }
4806 }
4807
4808 public void revokeUriPermission(IApplicationThread caller, Uri uri,
4809 int modeFlags) {
4810 synchronized(this) {
4811 final ProcessRecord r = getRecordForAppLocked(caller);
4812 if (r == null) {
4813 throw new SecurityException("Unable to find app for caller "
4814 + caller
4815 + " when revoking permission to uri " + uri);
4816 }
4817 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004818 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004819 return;
4820 }
4821
4822 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4823 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4824 if (modeFlags == 0) {
4825 return;
4826 }
4827
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004828 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004829
4830 final String authority = uri.getAuthority();
4831 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004832 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004833 if (cpr != null) {
4834 pi = cpr.info;
4835 } else {
4836 try {
4837 pi = pm.resolveContentProvider(authority,
4838 PackageManager.GET_URI_PERMISSION_PATTERNS);
4839 } catch (RemoteException ex) {
4840 }
4841 }
4842 if (pi == null) {
Dianne Hackborn98cfebc2011-10-18 13:17:33 -07004843 Slog.w(TAG, "No content provider found for permission revoke: "
4844 + uri.toSafeString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004845 return;
4846 }
4847
4848 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
4849 }
4850 }
4851
Dianne Hackborn7e269642010-08-25 19:50:20 -07004852 @Override
4853 public IBinder newUriPermissionOwner(String name) {
4854 synchronized(this) {
4855 UriPermissionOwner owner = new UriPermissionOwner(this, name);
4856 return owner.getExternalTokenLocked();
4857 }
4858 }
4859
4860 @Override
4861 public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg,
4862 Uri uri, int modeFlags) {
4863 synchronized(this) {
4864 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4865 if (owner == null) {
4866 throw new IllegalArgumentException("Unknown owner: " + token);
4867 }
4868 if (fromUid != Binder.getCallingUid()) {
4869 if (Binder.getCallingUid() != Process.myUid()) {
4870 // Only system code can grant URI permissions on behalf
4871 // of other users.
4872 throw new SecurityException("nice try");
4873 }
4874 }
4875 if (targetPkg == null) {
4876 throw new IllegalArgumentException("null target");
4877 }
4878 if (uri == null) {
4879 throw new IllegalArgumentException("null uri");
4880 }
4881
4882 grantUriPermissionLocked(fromUid, targetPkg, uri, modeFlags, owner);
4883 }
4884 }
4885
4886 @Override
4887 public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode) {
4888 synchronized(this) {
4889 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
4890 if (owner == null) {
4891 throw new IllegalArgumentException("Unknown owner: " + token);
4892 }
4893
4894 if (uri == null) {
4895 owner.removeUriPermissionsLocked(mode);
4896 } else {
4897 owner.removeUriPermissionLocked(uri, mode);
4898 }
4899 }
4900 }
4901
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004902 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
4903 synchronized (this) {
4904 ProcessRecord app =
4905 who != null ? getRecordForAppLocked(who) : null;
4906 if (app == null) return;
4907
4908 Message msg = Message.obtain();
4909 msg.what = WAIT_FOR_DEBUGGER_MSG;
4910 msg.obj = app;
4911 msg.arg1 = waiting ? 1 : 0;
4912 mHandler.sendMessage(msg);
4913 }
4914 }
4915
4916 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
Dianne Hackborn7d608422011-08-07 16:24:18 -07004917 final long homeAppMem = mProcessList.getMemLevel(ProcessList.HOME_APP_ADJ);
4918 final long hiddenAppMem = mProcessList.getMemLevel(ProcessList.HIDDEN_APP_MIN_ADJ);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004919 outInfo.availMem = Process.getFreeMemory();
Dianne Hackborn7d608422011-08-07 16:24:18 -07004920 outInfo.threshold = homeAppMem;
4921 outInfo.lowMemory = outInfo.availMem < (homeAppMem + ((hiddenAppMem-homeAppMem)/2));
4922 outInfo.hiddenAppThreshold = hiddenAppMem;
4923 outInfo.secondaryServerThreshold = mProcessList.getMemLevel(
4924 ProcessList.SECONDARY_SERVER_ADJ);
4925 outInfo.visibleAppThreshold = mProcessList.getMemLevel(
4926 ProcessList.VISIBLE_APP_ADJ);
4927 outInfo.foregroundAppThreshold = mProcessList.getMemLevel(
4928 ProcessList.FOREGROUND_APP_ADJ);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004929 }
4930
4931 // =========================================================
4932 // TASK MANAGEMENT
4933 // =========================================================
4934
4935 public List getTasks(int maxNum, int flags,
4936 IThumbnailReceiver receiver) {
4937 ArrayList list = new ArrayList();
4938
4939 PendingThumbnailsRecord pending = null;
4940 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004941 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004942
4943 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004944 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004945 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
4946 + ", receiver=" + receiver);
4947
4948 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
4949 != PackageManager.PERMISSION_GRANTED) {
4950 if (receiver != null) {
4951 // If the caller wants to wait for pending thumbnails,
4952 // it ain't gonna get them.
4953 try {
4954 receiver.finished();
4955 } catch (RemoteException ex) {
4956 }
4957 }
4958 String msg = "Permission Denial: getTasks() from pid="
4959 + Binder.getCallingPid()
4960 + ", uid=" + Binder.getCallingUid()
4961 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004962 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004963 throw new SecurityException(msg);
4964 }
4965
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004966 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004967 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004968 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004969 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004970 TaskRecord curTask = null;
4971 int numActivities = 0;
4972 int numRunning = 0;
4973 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004974 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004975 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004976 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004977
4978 // Initialize state for next task if needed.
4979 if (top == null ||
4980 (top.state == ActivityState.INITIALIZING
4981 && top.task == r.task)) {
4982 top = r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004983 curTask = r.task;
4984 numActivities = numRunning = 0;
4985 }
4986
4987 // Add 'r' into the current task.
4988 numActivities++;
4989 if (r.app != null && r.app.thread != null) {
4990 numRunning++;
4991 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004992
Joe Onorato8a9b2202010-02-26 18:56:32 -08004993 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004994 TAG, r.intent.getComponent().flattenToShortString()
4995 + ": task=" + r.task);
4996
4997 // If the next one is a different task, generate a new
4998 // TaskInfo entry for what we have.
4999 if (next == null || next.task != curTask) {
5000 ActivityManager.RunningTaskInfo ci
5001 = new ActivityManager.RunningTaskInfo();
5002 ci.id = curTask.taskId;
5003 ci.baseActivity = r.intent.getComponent();
5004 ci.topActivity = top.intent.getComponent();
Dianne Hackbornf26fd992011-04-08 18:14:09 -07005005 if (top.thumbHolder != null) {
5006 ci.description = top.thumbHolder.lastDescription;
5007 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005008 ci.numActivities = numActivities;
5009 ci.numRunning = numRunning;
5010 //System.out.println(
5011 // "#" + maxNum + ": " + " descr=" + ci.description);
5012 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005013 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005014 TAG, "State=" + top.state + "Idle=" + top.idle
5015 + " app=" + top.app
5016 + " thr=" + (top.app != null ? top.app.thread : null));
5017 if (top.state == ActivityState.RESUMED
5018 || top.state == ActivityState.PAUSING) {
5019 if (top.idle && top.app != null
5020 && top.app.thread != null) {
5021 topRecord = top;
5022 topThumbnail = top.app.thread;
5023 } else {
5024 top.thumbnailNeeded = true;
5025 }
5026 }
5027 if (pending == null) {
5028 pending = new PendingThumbnailsRecord(receiver);
5029 }
5030 pending.pendingRecords.add(top);
5031 }
5032 list.add(ci);
5033 maxNum--;
5034 top = null;
5035 }
5036 }
5037
5038 if (pending != null) {
5039 mPendingThumbnails.add(pending);
5040 }
5041 }
5042
Joe Onorato8a9b2202010-02-26 18:56:32 -08005043 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005044
5045 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005046 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005047 try {
5048 topThumbnail.requestThumbnail(topRecord);
5049 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005050 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005051 sendPendingThumbnail(null, topRecord, null, null, true);
5052 }
5053 }
5054
5055 if (pending == null && receiver != null) {
5056 // In this case all thumbnails were available and the client
5057 // is being asked to be told when the remaining ones come in...
5058 // which is unusually, since the top-most currently running
5059 // activity should never have a canned thumbnail! Oh well.
5060 try {
5061 receiver.finished();
5062 } catch (RemoteException ex) {
5063 }
5064 }
5065
5066 return list;
5067 }
5068
5069 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
5070 int flags) {
5071 synchronized (this) {
5072 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
5073 "getRecentTasks()");
5074
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005075 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07005076
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005077 final int N = mRecentTasks.size();
5078 ArrayList<ActivityManager.RecentTaskInfo> res
5079 = new ArrayList<ActivityManager.RecentTaskInfo>(
5080 maxNum < N ? maxNum : N);
5081 for (int i=0; i<N && maxNum > 0; i++) {
5082 TaskRecord tr = mRecentTasks.get(i);
Dianne Hackborn905577f2011-09-07 18:31:28 -07005083 // Return the entry if desired by the caller. We always return
5084 // the first entry, because callers always expect this to be the
5085 // forground app. We may filter others if the caller has
5086 // not supplied RECENT_WITH_EXCLUDED and there is some reason
5087 // we should exclude the entry.
5088 if (i == 0
5089 || ((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005090 || (tr.intent == null)
5091 || ((tr.intent.getFlags()
5092 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
5093 ActivityManager.RecentTaskInfo rti
5094 = new ActivityManager.RecentTaskInfo();
5095 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
Dianne Hackbornd94df452011-02-16 18:53:31 -08005096 rti.persistentId = tr.taskId;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005097 rti.baseIntent = new Intent(
5098 tr.intent != null ? tr.intent : tr.affinityIntent);
5099 rti.origActivity = tr.origActivity;
Dianne Hackbornd2835932010-12-13 16:28:46 -08005100 rti.description = tr.lastDescription;
5101
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07005102 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
5103 // Check whether this activity is currently available.
5104 try {
5105 if (rti.origActivity != null) {
5106 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
5107 continue;
5108 }
5109 } else if (rti.baseIntent != null) {
5110 if (pm.queryIntentActivities(rti.baseIntent,
5111 null, 0) == null) {
5112 continue;
5113 }
5114 }
5115 } catch (RemoteException e) {
5116 // Will never happen.
5117 }
5118 }
5119
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005120 res.add(rti);
5121 maxNum--;
5122 }
5123 }
5124 return res;
5125 }
5126 }
5127
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005128 private TaskRecord taskForIdLocked(int id) {
5129 final int N = mRecentTasks.size();
5130 for (int i=0; i<N; i++) {
5131 TaskRecord tr = mRecentTasks.get(i);
5132 if (tr.taskId == id) {
5133 return tr;
Dianne Hackbornd94df452011-02-16 18:53:31 -08005134 }
5135 }
5136 return null;
5137 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005138
5139 public ActivityManager.TaskThumbnails getTaskThumbnails(int id) {
5140 synchronized (this) {
5141 enforceCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER,
5142 "getTaskThumbnails()");
5143 TaskRecord tr = taskForIdLocked(id);
5144 if (tr != null) {
5145 return mMainStack.getTaskThumbnailsLocked(tr);
5146 }
5147 }
5148 return null;
5149 }
5150
5151 public boolean removeSubTask(int taskId, int subTaskIndex) {
5152 synchronized (this) {
5153 enforceCallingPermission(android.Manifest.permission.REMOVE_TASKS,
5154 "removeSubTask()");
5155 long ident = Binder.clearCallingIdentity();
5156 try {
5157 return mMainStack.removeTaskActivitiesLocked(taskId, subTaskIndex) != null;
5158 } finally {
5159 Binder.restoreCallingIdentity(ident);
5160 }
5161 }
5162 }
5163
Dianne Hackborn8894cc52011-07-01 16:28:17 -07005164 private void cleanUpRemovedTaskLocked(ActivityRecord root, boolean killProcesses) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005165 TaskRecord tr = root.task;
5166 Intent baseIntent = new Intent(
5167 tr.intent != null ? tr.intent : tr.affinityIntent);
5168 ComponentName component = baseIntent.getComponent();
5169 if (component == null) {
5170 Slog.w(TAG, "Now component for base intent of task: " + tr);
5171 return;
5172 }
5173
5174 // Find any running services associated with this app.
5175 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
5176 for (ServiceRecord sr : mServices.values()) {
5177 if (sr.packageName.equals(component.getPackageName())) {
5178 services.add(sr);
5179 }
5180 }
5181
5182 // Take care of any running services associated with the app.
5183 for (int i=0; i<services.size(); i++) {
5184 ServiceRecord sr = services.get(i);
5185 if (sr.startRequested) {
5186 if ((sr.serviceInfo.flags&ServiceInfo.FLAG_STOP_WITH_TASK) != 0) {
Dianne Hackborn8894cc52011-07-01 16:28:17 -07005187 Slog.i(TAG, "Stopping service " + sr.shortName + ": remove task");
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005188 stopServiceLocked(sr);
5189 } else {
5190 sr.pendingStarts.add(new ServiceRecord.StartItem(sr, true,
5191 sr.makeNextStartId(), baseIntent, -1));
5192 if (sr.app != null && sr.app.thread != null) {
5193 sendServiceArgsLocked(sr, false);
5194 }
5195 }
5196 }
5197 }
5198
Dianne Hackborn8894cc52011-07-01 16:28:17 -07005199 if (killProcesses) {
5200 // Find any running processes associated with this app.
5201 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
5202 SparseArray<ProcessRecord> appProcs
5203 = mProcessNames.getMap().get(component.getPackageName());
5204 if (appProcs != null) {
5205 for (int i=0; i<appProcs.size(); i++) {
5206 procs.add(appProcs.valueAt(i));
5207 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005208 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005209
Dianne Hackborn8894cc52011-07-01 16:28:17 -07005210 // Kill the running processes.
5211 for (int i=0; i<procs.size(); i++) {
5212 ProcessRecord pr = procs.get(i);
5213 if (pr.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {
5214 Slog.i(TAG, "Killing " + pr.toShortString() + ": remove task");
5215 EventLog.writeEvent(EventLogTags.AM_KILL, pr.pid,
5216 pr.processName, pr.setAdj, "remove task");
5217 Process.killProcessQuiet(pr.pid);
5218 } else {
5219 pr.waitingToKill = "remove task";
5220 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005221 }
5222 }
5223 }
5224
5225 public boolean removeTask(int taskId, int flags) {
5226 synchronized (this) {
5227 enforceCallingPermission(android.Manifest.permission.REMOVE_TASKS,
5228 "removeTask()");
5229 long ident = Binder.clearCallingIdentity();
5230 try {
5231 ActivityRecord r = mMainStack.removeTaskActivitiesLocked(taskId, -1);
5232 if (r != null) {
5233 mRecentTasks.remove(r.task);
Dianne Hackborn8894cc52011-07-01 16:28:17 -07005234 cleanUpRemovedTaskLocked(r,
5235 (flags&ActivityManager.REMOVE_TASK_KILL_PROCESS) != 0);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005236 return true;
Dianne Hackborneeb1dca2011-09-08 13:30:11 -07005237 } else {
5238 TaskRecord tr = null;
5239 int i=0;
5240 while (i < mRecentTasks.size()) {
5241 TaskRecord t = mRecentTasks.get(i);
5242 if (t.taskId == taskId) {
5243 tr = t;
5244 break;
5245 }
5246 i++;
5247 }
5248 if (tr != null) {
5249 if (tr.numActivities <= 0) {
5250 // Caller is just removing a recent task that is
5251 // not actively running. That is easy!
5252 mRecentTasks.remove(i);
5253 } else {
5254 Slog.w(TAG, "removeTask: task " + taskId
5255 + " does not have activities to remove, "
5256 + " but numActivities=" + tr.numActivities
5257 + ": " + tr);
5258 }
5259 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005260 }
5261 } finally {
5262 Binder.restoreCallingIdentity(ident);
5263 }
5264 }
5265 return false;
5266 }
Dianne Hackbornd94df452011-02-16 18:53:31 -08005267
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005268 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
5269 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005270 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005271 TaskRecord jt = startTask;
5272
5273 // First look backwards
5274 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005275 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005276 if (r.task != jt) {
5277 jt = r.task;
5278 if (affinity.equals(jt.affinity)) {
5279 return j;
5280 }
5281 }
5282 }
5283
5284 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005285 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005286 jt = startTask;
5287 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005288 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005289 if (r.task != jt) {
5290 if (affinity.equals(jt.affinity)) {
5291 return j;
5292 }
5293 jt = r.task;
5294 }
5295 }
5296
5297 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005298 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005299 return N-1;
5300 }
5301
5302 return -1;
5303 }
5304
5305 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005306 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005307 */
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005308 public void moveTaskToFront(int task, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005309 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5310 "moveTaskToFront()");
5311
5312 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005313 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5314 Binder.getCallingUid(), "Task to front")) {
5315 return;
5316 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005317 final long origId = Binder.clearCallingIdentity();
5318 try {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005319 TaskRecord tr = taskForIdLocked(task);
5320 if (tr != null) {
5321 if ((flags&ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
5322 mMainStack.mUserLeaving = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005323 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005324 if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
5325 // Caller wants the home activity moved with it. To accomplish this,
5326 // we'll just move the home task to the top first.
5327 mMainStack.moveHomeToFrontLocked();
5328 }
5329 mMainStack.moveTaskToFrontLocked(tr, null);
5330 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005331 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005332 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
5333 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005334 if (hr.task.taskId == task) {
Dianne Hackbornd94df452011-02-16 18:53:31 -08005335 if ((flags&ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
5336 mMainStack.mUserLeaving = true;
5337 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005338 if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
5339 // Caller wants the home activity moved with it. To accomplish this,
5340 // we'll just move the home task to the top first.
5341 mMainStack.moveHomeToFrontLocked();
5342 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005343 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005344 return;
5345 }
5346 }
5347 } finally {
5348 Binder.restoreCallingIdentity(origId);
5349 }
5350 }
5351 }
5352
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005353 public void moveTaskToBack(int task) {
5354 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5355 "moveTaskToBack()");
5356
5357 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005358 if (mMainStack.mResumedActivity != null
5359 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005360 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5361 Binder.getCallingUid(), "Task to back")) {
5362 return;
5363 }
5364 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005365 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005366 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005367 Binder.restoreCallingIdentity(origId);
5368 }
5369 }
5370
5371 /**
5372 * Moves an activity, and all of the other activities within the same task, to the bottom
5373 * of the history stack. The activity's order within the task is unchanged.
5374 *
5375 * @param token A reference to the activity we wish to move
5376 * @param nonRoot If false then this only works if the activity is the root
5377 * of a task; if true it will work for any activity in a task.
5378 * @return Returns true if the move completed, false if not.
5379 */
5380 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
5381 synchronized(this) {
5382 final long origId = Binder.clearCallingIdentity();
5383 int taskId = getTaskForActivityLocked(token, !nonRoot);
5384 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005385 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005386 }
5387 Binder.restoreCallingIdentity(origId);
5388 }
5389 return false;
5390 }
5391
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005392 public void moveTaskBackwards(int task) {
5393 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5394 "moveTaskBackwards()");
5395
5396 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005397 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5398 Binder.getCallingUid(), "Task backwards")) {
5399 return;
5400 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005401 final long origId = Binder.clearCallingIdentity();
5402 moveTaskBackwardsLocked(task);
5403 Binder.restoreCallingIdentity(origId);
5404 }
5405 }
5406
5407 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005408 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005409 }
5410
5411 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
5412 synchronized(this) {
5413 return getTaskForActivityLocked(token, onlyRoot);
5414 }
5415 }
5416
5417 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005418 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005419 TaskRecord lastTask = null;
5420 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005421 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005422 if (r == token) {
5423 if (!onlyRoot || lastTask != r.task) {
5424 return r.task.taskId;
5425 }
5426 return -1;
5427 }
5428 lastTask = r.task;
5429 }
5430
5431 return -1;
5432 }
5433
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005434 public void finishOtherInstances(IBinder token, ComponentName className) {
5435 synchronized(this) {
5436 final long origId = Binder.clearCallingIdentity();
5437
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005438 int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005439 TaskRecord lastTask = null;
5440 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005441 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005442 if (r.realActivity.equals(className)
5443 && r != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005444 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005445 null, "others")) {
5446 i--;
5447 N--;
5448 }
5449 }
5450 lastTask = r.task;
5451 }
5452
5453 Binder.restoreCallingIdentity(origId);
5454 }
5455 }
5456
5457 // =========================================================
5458 // THUMBNAILS
5459 // =========================================================
5460
5461 public void reportThumbnail(IBinder token,
5462 Bitmap thumbnail, CharSequence description) {
5463 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
5464 final long origId = Binder.clearCallingIdentity();
5465 sendPendingThumbnail(null, token, thumbnail, description, true);
5466 Binder.restoreCallingIdentity(origId);
5467 }
5468
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005469 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005470 Bitmap thumbnail, CharSequence description, boolean always) {
5471 TaskRecord task = null;
5472 ArrayList receivers = null;
5473
5474 //System.out.println("Send pending thumbnail: " + r);
5475
5476 synchronized(this) {
5477 if (r == null) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07005478 r = mMainStack.isInStackLocked(token);
5479 if (r == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005480 return;
5481 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005482 }
Dianne Hackbornf26fd992011-04-08 18:14:09 -07005483 if (thumbnail == null && r.thumbHolder != null) {
5484 thumbnail = r.thumbHolder.lastThumbnail;
5485 description = r.thumbHolder.lastDescription;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005486 }
5487 if (thumbnail == null && !always) {
5488 // If there is no thumbnail, and this entry is not actually
5489 // going away, then abort for now and pick up the next
5490 // thumbnail we get.
5491 return;
5492 }
5493 task = r.task;
5494
5495 int N = mPendingThumbnails.size();
5496 int i=0;
5497 while (i<N) {
5498 PendingThumbnailsRecord pr =
5499 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
5500 //System.out.println("Looking in " + pr.pendingRecords);
5501 if (pr.pendingRecords.remove(r)) {
5502 if (receivers == null) {
5503 receivers = new ArrayList();
5504 }
5505 receivers.add(pr);
5506 if (pr.pendingRecords.size() == 0) {
5507 pr.finished = true;
5508 mPendingThumbnails.remove(i);
5509 N--;
5510 continue;
5511 }
5512 }
5513 i++;
5514 }
5515 }
5516
5517 if (receivers != null) {
5518 final int N = receivers.size();
5519 for (int i=0; i<N; i++) {
5520 try {
5521 PendingThumbnailsRecord pr =
5522 (PendingThumbnailsRecord)receivers.get(i);
5523 pr.receiver.newThumbnail(
5524 task != null ? task.taskId : -1, thumbnail, description);
5525 if (pr.finished) {
5526 pr.receiver.finished();
5527 }
5528 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005529 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005530 }
5531 }
5532 }
5533 }
5534
5535 // =========================================================
5536 // CONTENT PROVIDERS
5537 // =========================================================
5538
Jeff Brown10e89712011-07-08 18:52:57 -07005539 private final List<ProviderInfo> generateApplicationProvidersLocked(ProcessRecord app) {
5540 List<ProviderInfo> providers = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005541 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005542 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005543 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005544 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005545 } catch (RemoteException ex) {
5546 }
5547 if (providers != null) {
5548 final int N = providers.size();
5549 for (int i=0; i<N; i++) {
5550 ProviderInfo cpi =
5551 (ProviderInfo)providers.get(i);
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07005552 ComponentName comp = new ComponentName(cpi.packageName, cpi.name);
5553 ContentProviderRecord cpr = mProvidersByClass.get(comp);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005554 if (cpr == null) {
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07005555 cpr = new ContentProviderRecord(cpi, app.info, comp);
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07005556 mProvidersByClass.put(comp, cpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005557 }
5558 app.pubProviders.put(cpi.name, cpr);
5559 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005560 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005561 }
5562 }
5563 return providers;
5564 }
5565
5566 private final String checkContentProviderPermissionLocked(
Dianne Hackbornb424b632010-08-18 15:59:05 -07005567 ProviderInfo cpi, ProcessRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005568 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
5569 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
5570 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005571 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005572 == PackageManager.PERMISSION_GRANTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005573 return null;
5574 }
5575 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005576 cpi.applicationInfo.uid, cpi.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005577 == PackageManager.PERMISSION_GRANTED) {
5578 return null;
5579 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005580
5581 PathPermission[] pps = cpi.pathPermissions;
5582 if (pps != null) {
5583 int i = pps.length;
5584 while (i > 0) {
5585 i--;
5586 PathPermission pp = pps[i];
5587 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005588 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005589 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005590 return null;
5591 }
5592 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005593 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005594 == PackageManager.PERMISSION_GRANTED) {
5595 return null;
5596 }
5597 }
5598 }
5599
Dianne Hackbornb424b632010-08-18 15:59:05 -07005600 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
5601 if (perms != null) {
5602 for (Map.Entry<Uri, UriPermission> uri : perms.entrySet()) {
5603 if (uri.getKey().getAuthority().equals(cpi.authority)) {
5604 return null;
5605 }
5606 }
5607 }
5608
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005609 String msg;
5610 if (!cpi.exported) {
5611 msg = "Permission Denial: opening provider " + cpi.name
5612 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5613 + ", uid=" + callingUid + ") that is not exported from uid "
5614 + cpi.applicationInfo.uid;
5615 } else {
5616 msg = "Permission Denial: opening provider " + cpi.name
5617 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5618 + ", uid=" + callingUid + ") requires "
5619 + cpi.readPermission + " or " + cpi.writePermission;
5620 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005621 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005622 return msg;
5623 }
5624
Dianne Hackborn295e3c22011-08-25 13:19:08 -07005625 boolean incProviderCount(ProcessRecord r, ContentProviderRecord cpr) {
5626 if (r != null) {
5627 Integer cnt = r.conProviders.get(cpr);
5628 if (DEBUG_PROVIDER) Slog.v(TAG,
5629 "Adding provider requested by "
5630 + r.processName + " from process "
5631 + cpr.info.processName + ": " + cpr.name.flattenToShortString()
5632 + " cnt=" + (cnt == null ? 1 : cnt));
5633 if (cnt == null) {
5634 cpr.clients.add(r);
5635 r.conProviders.put(cpr, new Integer(1));
5636 return true;
5637 } else {
5638 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5639 }
5640 } else {
5641 cpr.externals++;
5642 }
5643 return false;
5644 }
5645
5646 boolean decProviderCount(ProcessRecord r, ContentProviderRecord cpr) {
5647 if (r != null) {
5648 Integer cnt = r.conProviders.get(cpr);
5649 if (DEBUG_PROVIDER) Slog.v(TAG,
5650 "Removing provider requested by "
5651 + r.processName + " from process "
5652 + cpr.info.processName + ": " + cpr.name.flattenToShortString()
5653 + " cnt=" + cnt);
5654 if (cnt == null || cnt.intValue() <= 1) {
5655 cpr.clients.remove(r);
5656 r.conProviders.remove(cpr);
5657 return true;
5658 } else {
5659 r.conProviders.put(cpr, new Integer(cnt.intValue()-1));
5660 }
5661 } else {
5662 cpr.externals++;
5663 }
5664 return false;
5665 }
5666
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005667 private final ContentProviderHolder getContentProviderImpl(
5668 IApplicationThread caller, String name) {
5669 ContentProviderRecord cpr;
5670 ProviderInfo cpi = null;
5671
5672 synchronized(this) {
5673 ProcessRecord r = null;
5674 if (caller != null) {
5675 r = getRecordForAppLocked(caller);
5676 if (r == null) {
5677 throw new SecurityException(
5678 "Unable to find app for caller " + caller
5679 + " (pid=" + Binder.getCallingPid()
5680 + ") when getting content provider " + name);
5681 }
5682 }
5683
5684 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07005685 cpr = mProvidersByName.get(name);
Dianne Hackborn295e3c22011-08-25 13:19:08 -07005686 boolean providerRunning = cpr != null;
5687 if (providerRunning) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005688 cpi = cpr.info;
Dianne Hackbornb424b632010-08-18 15:59:05 -07005689 String msg;
5690 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5691 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005692 }
5693
5694 if (r != null && cpr.canRunHere(r)) {
5695 // This provider has been published or is in the process
5696 // of being published... but it is also allowed to run
5697 // in the caller's process, so don't make a connection
5698 // and just let the caller instantiate its own instance.
5699 if (cpr.provider != null) {
5700 // don't give caller the provider object, it needs
5701 // to make its own.
5702 cpr = new ContentProviderRecord(cpr);
5703 }
5704 return cpr;
5705 }
5706
5707 final long origId = Binder.clearCallingIdentity();
5708
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005709 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005710 // return it right away.
Dianne Hackborn295e3c22011-08-25 13:19:08 -07005711 final boolean countChanged = incProviderCount(r, cpr);
5712 if (countChanged) {
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07005713 if (cpr.proc != null && r.setAdj <= ProcessList.PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -07005714 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07005715 // make sure to count it as being accessed and thus
5716 // back up on the LRU list. This is good because
5717 // content providers are often expensive to start.
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07005718 updateLruProcessLocked(cpr.proc, false, true);
Dianne Hackborn906497c2010-05-10 15:57:38 -07005719 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07005720 }
5721
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07005722 if (cpr.proc != null) {
Dianne Hackborn295e3c22011-08-25 13:19:08 -07005723 if (false) {
5724 if (cpr.name.flattenToShortString().equals(
5725 "com.android.providers.calendar/.CalendarProvider2")) {
5726 Slog.v(TAG, "****************** KILLING "
5727 + cpr.name.flattenToShortString());
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07005728 Process.killProcess(cpr.proc.pid);
Dianne Hackborn295e3c22011-08-25 13:19:08 -07005729 }
5730 }
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07005731 boolean success = updateOomAdjLocked(cpr.proc);
Dianne Hackborn295e3c22011-08-25 13:19:08 -07005732 if (DEBUG_PROVIDER) Slog.i(TAG, "Adjust success: " + success);
5733 // NOTE: there is still a race here where a signal could be
5734 // pending on the process even though we managed to update its
5735 // adj level. Not sure what to do about this, but at least
5736 // the race is now smaller.
5737 if (!success) {
5738 // Uh oh... it looks like the provider's process
5739 // has been killed on us. We need to wait for a new
5740 // process to be started, and make sure its death
5741 // doesn't kill our process.
5742 Slog.i(TAG,
5743 "Existing provider " + cpr.name.flattenToShortString()
5744 + " is crashing; detaching " + r);
5745 boolean lastRef = decProviderCount(r, cpr);
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07005746 appDiedLocked(cpr.proc, cpr.proc.pid, cpr.proc.thread);
Dianne Hackborn295e3c22011-08-25 13:19:08 -07005747 if (!lastRef) {
5748 // This wasn't the last ref our process had on
5749 // the provider... we have now been killed, bail.
5750 return null;
5751 }
5752 providerRunning = false;
5753 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005754 }
5755
5756 Binder.restoreCallingIdentity(origId);
Dianne Hackborn295e3c22011-08-25 13:19:08 -07005757 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005758
Dianne Hackborn295e3c22011-08-25 13:19:08 -07005759 if (!providerRunning) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005760 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005761 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005762 resolveContentProvider(name,
5763 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005764 } catch (RemoteException ex) {
5765 }
5766 if (cpi == null) {
5767 return null;
5768 }
5769
Dianne Hackbornb424b632010-08-18 15:59:05 -07005770 String msg;
5771 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5772 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005773 }
5774
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07005775 if (!mProcessesReady && !mDidUpdate && !mWaitingUpdate
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005776 && !cpi.processName.equals("system")) {
5777 // If this content provider does not run in the system
5778 // process, and the system is not yet ready to run other
5779 // processes, then fail fast instead of hanging.
5780 throw new IllegalArgumentException(
5781 "Attempt to launch content provider before system ready");
5782 }
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07005783
5784 ComponentName comp = new ComponentName(cpi.packageName, cpi.name);
5785 cpr = mProvidersByClass.get(comp);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005786 final boolean firstClass = cpr == null;
5787 if (firstClass) {
5788 try {
5789 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005790 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005791 getApplicationInfo(
5792 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005793 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005794 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005795 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005796 + cpi.name);
5797 return null;
5798 }
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07005799 cpr = new ContentProviderRecord(cpi, ai, comp);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005800 } catch (RemoteException ex) {
5801 // pm is in same process, this will never happen.
5802 }
5803 }
5804
5805 if (r != null && cpr.canRunHere(r)) {
5806 // If this is a multiprocess provider, then just return its
5807 // info and allow the caller to instantiate it. Only do
5808 // this if the provider is the same user as the caller's
5809 // process, or can run as root (so can be in any process).
5810 return cpr;
5811 }
5812
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005813 if (DEBUG_PROVIDER) {
5814 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08005815 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005816 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005817 }
5818
5819 // This is single process, and our app is now connecting to it.
5820 // See if we are already in the process of launching this
5821 // provider.
5822 final int N = mLaunchingProviders.size();
5823 int i;
5824 for (i=0; i<N; i++) {
5825 if (mLaunchingProviders.get(i) == cpr) {
5826 break;
5827 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005828 }
5829
5830 // If the provider is not already being launched, then get it
5831 // started.
5832 if (i >= N) {
5833 final long origId = Binder.clearCallingIdentity();
Dianne Hackborne7f97212011-02-24 14:40:20 -08005834
5835 try {
5836 // Content provider is now in use, its package can't be stopped.
5837 try {
5838 AppGlobals.getPackageManager().setPackageStoppedState(
5839 cpr.appInfo.packageName, false);
5840 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08005841 } catch (IllegalArgumentException e) {
5842 Slog.w(TAG, "Failed trying to unstop package "
5843 + cpr.appInfo.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08005844 }
5845
5846 ProcessRecord proc = startProcessLocked(cpi.processName,
5847 cpr.appInfo, false, 0, "content provider",
5848 new ComponentName(cpi.applicationInfo.packageName,
5849 cpi.name), false);
5850 if (proc == null) {
5851 Slog.w(TAG, "Unable to launch app "
5852 + cpi.applicationInfo.packageName + "/"
5853 + cpi.applicationInfo.uid + " for provider "
5854 + name + ": process is bad");
5855 return null;
5856 }
5857 cpr.launchingApp = proc;
5858 mLaunchingProviders.add(cpr);
5859 } finally {
5860 Binder.restoreCallingIdentity(origId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005861 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005862 }
5863
5864 // Make sure the provider is published (the same provider class
5865 // may be published under multiple names).
5866 if (firstClass) {
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07005867 mProvidersByClass.put(comp, cpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005868 }
5869 mProvidersByName.put(name, cpr);
Dianne Hackborn295e3c22011-08-25 13:19:08 -07005870 incProviderCount(r, cpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005871 }
5872 }
5873
5874 // Wait for the provider to be published...
5875 synchronized (cpr) {
5876 while (cpr.provider == null) {
5877 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005878 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005879 + cpi.applicationInfo.packageName + "/"
5880 + cpi.applicationInfo.uid + " for provider "
5881 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08005882 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005883 cpi.applicationInfo.packageName,
5884 cpi.applicationInfo.uid, name);
5885 return null;
5886 }
5887 try {
5888 cpr.wait();
5889 } catch (InterruptedException ex) {
5890 }
5891 }
5892 }
5893 return cpr;
5894 }
5895
5896 public final ContentProviderHolder getContentProvider(
5897 IApplicationThread caller, String name) {
5898 if (caller == null) {
5899 String msg = "null IApplicationThread when getting content provider "
5900 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005901 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005902 throw new SecurityException(msg);
5903 }
5904
5905 return getContentProviderImpl(caller, name);
5906 }
5907
5908 private ContentProviderHolder getContentProviderExternal(String name) {
5909 return getContentProviderImpl(null, name);
5910 }
5911
5912 /**
5913 * Drop a content provider from a ProcessRecord's bookkeeping
5914 * @param cpr
5915 */
5916 public void removeContentProvider(IApplicationThread caller, String name) {
5917 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005918 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005919 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005920 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005921 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005922 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005923 return;
5924 }
5925 final ProcessRecord r = getRecordForAppLocked(caller);
5926 if (r == null) {
5927 throw new SecurityException(
5928 "Unable to find app for caller " + caller +
5929 " when removing content provider " + name);
5930 }
5931 //update content provider record entry info
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07005932 ComponentName comp = new ComponentName(cpr.info.packageName, cpr.info.name);
5933 ContentProviderRecord localCpr = mProvidersByClass.get(comp);
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07005934 if (localCpr.proc == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005935 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08005936 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005937 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005938 return;
5939 } else {
Dianne Hackborn295e3c22011-08-25 13:19:08 -07005940 if (decProviderCount(r, localCpr)) {
5941 updateOomAdjLocked();
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07005942 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005943 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005944 }
5945 }
5946
5947 private void removeContentProviderExternal(String name) {
5948 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07005949 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005950 if(cpr == null) {
5951 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08005952 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005953 return;
5954 }
5955
5956 //update content provider record entry info
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07005957 ComponentName comp = new ComponentName(cpr.info.packageName, cpr.info.name);
5958 ContentProviderRecord localCpr = mProvidersByClass.get(comp);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005959 localCpr.externals--;
5960 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005961 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005962 }
5963 updateOomAdjLocked();
5964 }
5965 }
5966
5967 public final void publishContentProviders(IApplicationThread caller,
5968 List<ContentProviderHolder> providers) {
5969 if (providers == null) {
5970 return;
5971 }
5972
5973 synchronized(this) {
5974 final ProcessRecord r = getRecordForAppLocked(caller);
5975 if (r == null) {
5976 throw new SecurityException(
5977 "Unable to find app for caller " + caller
5978 + " (pid=" + Binder.getCallingPid()
5979 + ") when publishing content providers");
5980 }
5981
5982 final long origId = Binder.clearCallingIdentity();
5983
5984 final int N = providers.size();
5985 for (int i=0; i<N; i++) {
5986 ContentProviderHolder src = providers.get(i);
5987 if (src == null || src.info == null || src.provider == null) {
5988 continue;
5989 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07005990 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005991 if (dst != null) {
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07005992 ComponentName comp = new ComponentName(dst.info.packageName, dst.info.name);
5993 mProvidersByClass.put(comp, dst);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005994 String names[] = dst.info.authority.split(";");
5995 for (int j = 0; j < names.length; j++) {
5996 mProvidersByName.put(names[j], dst);
5997 }
5998
5999 int NL = mLaunchingProviders.size();
6000 int j;
6001 for (j=0; j<NL; j++) {
6002 if (mLaunchingProviders.get(j) == dst) {
6003 mLaunchingProviders.remove(j);
6004 j--;
6005 NL--;
6006 }
6007 }
6008 synchronized (dst) {
6009 dst.provider = src.provider;
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07006010 dst.proc = r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006011 dst.notifyAll();
6012 }
6013 updateOomAdjLocked(r);
6014 }
6015 }
6016
6017 Binder.restoreCallingIdentity(origId);
6018 }
6019 }
6020
6021 public static final void installSystemProviders() {
Jeff Brown10e89712011-07-08 18:52:57 -07006022 List<ProviderInfo> providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06006023 synchronized (mSelf) {
6024 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
6025 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08006026 if (providers != null) {
6027 for (int i=providers.size()-1; i>=0; i--) {
6028 ProviderInfo pi = (ProviderInfo)providers.get(i);
6029 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
6030 Slog.w(TAG, "Not installing system proc provider " + pi.name
6031 + ": not system .apk");
6032 providers.remove(i);
6033 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08006034 }
6035 }
6036 }
Josh Bartel2ecce342010-02-25 10:55:48 -06006037 if (providers != null) {
6038 mSystemThread.installSystemProviders(providers);
6039 }
Svetoslav Ganov54d068e2011-03-02 12:58:40 -08006040
6041 mSelf.mCoreSettingsObserver = new CoreSettingsObserver(mSelf);
Mark Brophyc6350272011-08-05 16:16:39 +01006042
6043 mSelf.mUsageStatsService.monitorPackages();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006044 }
6045
Dianne Hackborncca1f0e2010-09-26 18:34:53 -07006046 /**
6047 * Allows app to retrieve the MIME type of a URI without having permission
6048 * to access its content provider.
6049 *
6050 * CTS tests for this functionality can be run with "runtest cts-appsecurity".
6051 *
6052 * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
6053 * src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
6054 */
6055 public String getProviderMimeType(Uri uri) {
6056 final String name = uri.getAuthority();
6057 final long ident = Binder.clearCallingIdentity();
6058 ContentProviderHolder holder = null;
6059
6060 try {
6061 holder = getContentProviderExternal(name);
6062 if (holder != null) {
6063 return holder.provider.getType(uri);
6064 }
6065 } catch (RemoteException e) {
6066 Log.w(TAG, "Content provider dead retrieving " + uri, e);
6067 return null;
6068 } finally {
6069 if (holder != null) {
6070 removeContentProviderExternal(name);
6071 }
6072 Binder.restoreCallingIdentity(ident);
6073 }
6074
6075 return null;
6076 }
6077
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006078 // =========================================================
6079 // GLOBAL MANAGEMENT
6080 // =========================================================
6081
6082 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
6083 ApplicationInfo info, String customProcess) {
6084 String proc = customProcess != null ? customProcess : info.processName;
6085 BatteryStatsImpl.Uid.Proc ps = null;
6086 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
6087 synchronized (stats) {
6088 ps = stats.getProcessStatsLocked(info.uid, proc);
6089 }
6090 return new ProcessRecord(ps, thread, info, proc);
6091 }
6092
6093 final ProcessRecord addAppLocked(ApplicationInfo info) {
6094 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
6095
6096 if (app == null) {
6097 app = newProcessRecordLocked(null, info, null);
6098 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006099 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006100 }
6101
Dianne Hackborne7f97212011-02-24 14:40:20 -08006102 // This package really, really can not be stopped.
6103 try {
6104 AppGlobals.getPackageManager().setPackageStoppedState(
6105 info.packageName, false);
6106 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08006107 } catch (IllegalArgumentException e) {
6108 Slog.w(TAG, "Failed trying to unstop package "
6109 + info.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08006110 }
6111
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006112 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
6113 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
6114 app.persistent = true;
Dianne Hackborn7d608422011-08-07 16:24:18 -07006115 app.maxAdj = ProcessList.CORE_SERVER_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006116 }
6117 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
6118 mPersistentStartingProcesses.add(app);
6119 startProcessLocked(app, "added application", app.processName);
6120 }
6121
6122 return app;
6123 }
6124
6125 public void unhandledBack() {
6126 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
6127 "unhandledBack()");
6128
6129 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006130 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08006131 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006132 TAG, "Performing unhandledBack(): stack size = " + count);
6133 if (count > 1) {
6134 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006135 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006136 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
6137 Binder.restoreCallingIdentity(origId);
6138 }
6139 }
6140 }
6141
6142 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
6143 String name = uri.getAuthority();
6144 ContentProviderHolder cph = getContentProviderExternal(name);
6145 ParcelFileDescriptor pfd = null;
6146 if (cph != null) {
6147 // We record the binder invoker's uid in thread-local storage before
6148 // going to the content provider to open the file. Later, in the code
6149 // that handles all permissions checks, we look for this uid and use
6150 // that rather than the Activity Manager's own uid. The effect is that
6151 // we do the check against the caller's permissions even though it looks
6152 // to the content provider like the Activity Manager itself is making
6153 // the request.
6154 sCallerIdentity.set(new Identity(
6155 Binder.getCallingPid(), Binder.getCallingUid()));
6156 try {
6157 pfd = cph.provider.openFile(uri, "r");
6158 } catch (FileNotFoundException e) {
6159 // do nothing; pfd will be returned null
6160 } finally {
6161 // Ensure that whatever happens, we clean up the identity state
6162 sCallerIdentity.remove();
6163 }
6164
6165 // We've got the fd now, so we're done with the provider.
6166 removeContentProviderExternal(name);
6167 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006168 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006169 }
6170 return pfd;
6171 }
6172
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006173 // Actually is sleeping or shutting down or whatever else in the future
6174 // is an inactive state.
6175 public boolean isSleeping() {
6176 return mSleeping || mShuttingDown;
6177 }
6178
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006179 public void goingToSleep() {
6180 synchronized(this) {
6181 mSleeping = true;
6182 mWindowManager.setEventDispatching(false);
6183
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006184 mMainStack.stopIfSleepingLocked();
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07006185
6186 // Initialize the wake times of all processes.
Dianne Hackborn287952c2010-09-22 22:34:31 -07006187 checkExcessivePowerUsageLocked(false);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07006188 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
6189 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07006190 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006191 }
6192 }
6193
Dianne Hackborn55280a92009-05-07 15:53:46 -07006194 public boolean shutdown(int timeout) {
6195 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
6196 != PackageManager.PERMISSION_GRANTED) {
6197 throw new SecurityException("Requires permission "
6198 + android.Manifest.permission.SHUTDOWN);
6199 }
6200
6201 boolean timedout = false;
6202
6203 synchronized(this) {
6204 mShuttingDown = true;
6205 mWindowManager.setEventDispatching(false);
6206
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006207 if (mMainStack.mResumedActivity != null) {
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006208 mMainStack.stopIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07006209 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006210 while (mMainStack.mResumedActivity != null
6211 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07006212 long delay = endTime - System.currentTimeMillis();
6213 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006214 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07006215 timedout = true;
6216 break;
6217 }
6218 try {
6219 this.wait();
6220 } catch (InterruptedException e) {
6221 }
6222 }
6223 }
6224 }
6225
6226 mUsageStatsService.shutdown();
6227 mBatteryStatsService.shutdown();
6228
6229 return timedout;
6230 }
6231
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006232 public final void activitySlept(IBinder token) {
6233 if (localLOGV) Slog.v(
6234 TAG, "Activity slept: token=" + token);
6235
6236 ActivityRecord r = null;
6237
6238 final long origId = Binder.clearCallingIdentity();
6239
6240 synchronized (this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07006241 r = mMainStack.isInStackLocked(token);
6242 if (r != null) {
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006243 mMainStack.activitySleptLocked(r);
6244 }
6245 }
6246
6247 Binder.restoreCallingIdentity(origId);
6248 }
6249
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006250 public void wakingUp() {
6251 synchronized(this) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006252 mWindowManager.setEventDispatching(true);
6253 mSleeping = false;
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006254 mMainStack.awakeFromSleepingLocked();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006255 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006256 }
6257 }
6258
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006259 public void stopAppSwitches() {
6260 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
6261 != PackageManager.PERMISSION_GRANTED) {
6262 throw new SecurityException("Requires permission "
6263 + android.Manifest.permission.STOP_APP_SWITCHES);
6264 }
6265
6266 synchronized(this) {
6267 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
6268 + APP_SWITCH_DELAY_TIME;
6269 mDidAppSwitch = false;
6270 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
6271 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
6272 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
6273 }
6274 }
6275
6276 public void resumeAppSwitches() {
6277 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
6278 != PackageManager.PERMISSION_GRANTED) {
6279 throw new SecurityException("Requires permission "
6280 + android.Manifest.permission.STOP_APP_SWITCHES);
6281 }
6282
6283 synchronized(this) {
6284 // Note that we don't execute any pending app switches... we will
6285 // let those wait until either the timeout, or the next start
6286 // activity request.
6287 mAppSwitchesAllowedTime = 0;
6288 }
6289 }
6290
6291 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
6292 String name) {
6293 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
6294 return true;
6295 }
6296
6297 final int perm = checkComponentPermission(
6298 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08006299 callingUid, -1, true);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006300 if (perm == PackageManager.PERMISSION_GRANTED) {
6301 return true;
6302 }
6303
Joe Onorato8a9b2202010-02-26 18:56:32 -08006304 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006305 return false;
6306 }
6307
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006308 public void setDebugApp(String packageName, boolean waitForDebugger,
6309 boolean persistent) {
6310 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
6311 "setDebugApp()");
6312
6313 // Note that this is not really thread safe if there are multiple
6314 // callers into it at the same time, but that's not a situation we
6315 // care about.
6316 if (persistent) {
6317 final ContentResolver resolver = mContext.getContentResolver();
6318 Settings.System.putString(
6319 resolver, Settings.System.DEBUG_APP,
6320 packageName);
6321 Settings.System.putInt(
6322 resolver, Settings.System.WAIT_FOR_DEBUGGER,
6323 waitForDebugger ? 1 : 0);
6324 }
6325
6326 synchronized (this) {
6327 if (!persistent) {
6328 mOrigDebugApp = mDebugApp;
6329 mOrigWaitForDebugger = mWaitForDebugger;
6330 }
6331 mDebugApp = packageName;
6332 mWaitForDebugger = waitForDebugger;
6333 mDebugTransient = !persistent;
6334 if (packageName != null) {
6335 final long origId = Binder.clearCallingIdentity();
Christopher Tate3dacd842011-08-19 14:56:15 -07006336 forceStopPackageLocked(packageName, -1, false, false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006337 Binder.restoreCallingIdentity(origId);
6338 }
6339 }
6340 }
6341
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07006342 void setProfileApp(ApplicationInfo app, String processName, String profileFile,
6343 ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
6344 synchronized (this) {
6345 boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
6346 if (!isDebuggable) {
6347 if ((app.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
6348 throw new SecurityException("Process not debuggable: " + app.packageName);
6349 }
6350 }
6351 mProfileApp = processName;
6352 mProfileFile = profileFile;
6353 if (mProfileFd != null) {
6354 try {
6355 mProfileFd.close();
6356 } catch (IOException e) {
6357 }
6358 mProfileFd = null;
6359 }
6360 mProfileFd = profileFd;
6361 mProfileType = 0;
6362 mAutoStopProfiler = autoStopProfiler;
6363 }
6364 }
6365
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006366 public void setAlwaysFinish(boolean enabled) {
6367 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
6368 "setAlwaysFinish()");
6369
6370 Settings.System.putInt(
6371 mContext.getContentResolver(),
6372 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
6373
6374 synchronized (this) {
6375 mAlwaysFinishActivities = enabled;
6376 }
6377 }
6378
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006379 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006380 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006381 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006382 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006383 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006384 }
6385 }
6386
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08006387 public boolean isUserAMonkey() {
6388 // For now the fact that there is a controller implies
6389 // we have a monkey.
6390 synchronized (this) {
6391 return mController != null;
6392 }
6393 }
6394
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006395 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06006396 synchronized (this) {
6397 mWatchers.register(watcher);
6398 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006399 }
6400
6401 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06006402 synchronized (this) {
6403 mWatchers.unregister(watcher);
6404 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006405 }
6406
Jeff Sharkeya4620792011-05-20 15:29:23 -07006407 public void registerProcessObserver(IProcessObserver observer) {
6408 mProcessObservers.register(observer);
6409 }
6410
6411 public void unregisterProcessObserver(IProcessObserver observer) {
6412 mProcessObservers.unregister(observer);
6413 }
6414
Daniel Sandler69a48172010-06-23 16:29:36 -04006415 public void setImmersive(IBinder token, boolean immersive) {
6416 synchronized(this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07006417 ActivityRecord r = mMainStack.isInStackLocked(token);
6418 if (r == null) {
Daniel Sandler69a48172010-06-23 16:29:36 -04006419 throw new IllegalArgumentException();
6420 }
Daniel Sandler69a48172010-06-23 16:29:36 -04006421 r.immersive = immersive;
6422 }
6423 }
6424
6425 public boolean isImmersive(IBinder token) {
6426 synchronized (this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07006427 ActivityRecord r = mMainStack.isInStackLocked(token);
6428 if (r == null) {
Daniel Sandler69a48172010-06-23 16:29:36 -04006429 throw new IllegalArgumentException();
6430 }
Daniel Sandler69a48172010-06-23 16:29:36 -04006431 return r.immersive;
6432 }
6433 }
6434
6435 public boolean isTopActivityImmersive() {
6436 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006437 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Daniel Sandler69a48172010-06-23 16:29:36 -04006438 return (r != null) ? r.immersive : false;
6439 }
6440 }
6441
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006442 public final void enterSafeMode() {
6443 synchronized(this) {
6444 // It only makes sense to do this before the system is ready
6445 // and started launching other packages.
6446 if (!mSystemReady) {
6447 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006448 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006449 } catch (RemoteException e) {
6450 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006451 }
6452 }
6453 }
6454
Jeff Brownb09abc12011-01-13 21:08:27 -08006455 public final void showSafeModeOverlay() {
6456 View v = LayoutInflater.from(mContext).inflate(
6457 com.android.internal.R.layout.safe_mode, null);
6458 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
6459 lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
6460 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
6461 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
6462 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
6463 lp.format = v.getBackground().getOpacity();
6464 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
6465 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
6466 ((WindowManager)mContext.getSystemService(
6467 Context.WINDOW_SERVICE)).addView(v, lp);
6468 }
6469
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006470 public void noteWakeupAlarm(IIntentSender sender) {
6471 if (!(sender instanceof PendingIntentRecord)) {
6472 return;
6473 }
6474 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
6475 synchronized (stats) {
6476 if (mBatteryStatsService.isOnBattery()) {
6477 mBatteryStatsService.enforceCallingPermission();
6478 PendingIntentRecord rec = (PendingIntentRecord)sender;
6479 int MY_UID = Binder.getCallingUid();
6480 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
6481 BatteryStatsImpl.Uid.Pkg pkg =
6482 stats.getPackageStatsLocked(uid, rec.key.packageName);
6483 pkg.incWakeupsLocked();
6484 }
6485 }
6486 }
6487
Dianne Hackborn64825172011-03-02 21:32:58 -08006488 public boolean killPids(int[] pids, String pReason, boolean secure) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006489 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006490 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006491 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006492 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006493 // XXX Note: don't acquire main activity lock here, because the window
6494 // manager calls in with its locks held.
6495
6496 boolean killed = false;
6497 synchronized (mPidsSelfLocked) {
6498 int[] types = new int[pids.length];
6499 int worstType = 0;
6500 for (int i=0; i<pids.length; i++) {
6501 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6502 if (proc != null) {
6503 int type = proc.setAdj;
6504 types[i] = type;
6505 if (type > worstType) {
6506 worstType = type;
6507 }
6508 }
6509 }
6510
Dianne Hackborn64825172011-03-02 21:32:58 -08006511 // If the worst oom_adj is somewhere in the hidden proc LRU range,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006512 // then constrain it so we will kill all hidden procs.
Dianne Hackborn7d608422011-08-07 16:24:18 -07006513 if (worstType < ProcessList.EMPTY_APP_ADJ && worstType > ProcessList.HIDDEN_APP_MIN_ADJ) {
6514 worstType = ProcessList.HIDDEN_APP_MIN_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006515 }
Dianne Hackborn64825172011-03-02 21:32:58 -08006516
6517 // If this is not a secure call, don't let it kill processes that
6518 // are important.
Dianne Hackborn7d608422011-08-07 16:24:18 -07006519 if (!secure && worstType < ProcessList.SECONDARY_SERVER_ADJ) {
6520 worstType = ProcessList.SECONDARY_SERVER_ADJ;
Dianne Hackborn64825172011-03-02 21:32:58 -08006521 }
6522
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006523 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006524 for (int i=0; i<pids.length; i++) {
6525 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6526 if (proc == null) {
6527 continue;
6528 }
6529 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006530 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07006531 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006532 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
6533 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006534 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006535 proc.killedBackground = true;
6536 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006537 }
6538 }
6539 }
6540 return killed;
6541 }
6542
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006543 public final void startRunning(String pkg, String cls, String action,
6544 String data) {
6545 synchronized(this) {
6546 if (mStartRunning) {
6547 return;
6548 }
6549 mStartRunning = true;
6550 mTopComponent = pkg != null && cls != null
6551 ? new ComponentName(pkg, cls) : null;
6552 mTopAction = action != null ? action : Intent.ACTION_MAIN;
6553 mTopData = data;
6554 if (!mSystemReady) {
6555 return;
6556 }
6557 }
6558
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006559 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006560 }
6561
6562 private void retrieveSettings() {
6563 final ContentResolver resolver = mContext.getContentResolver();
6564 String debugApp = Settings.System.getString(
6565 resolver, Settings.System.DEBUG_APP);
6566 boolean waitForDebugger = Settings.System.getInt(
6567 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
6568 boolean alwaysFinishActivities = Settings.System.getInt(
6569 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
6570
6571 Configuration configuration = new Configuration();
6572 Settings.System.getConfiguration(resolver, configuration);
6573
6574 synchronized (this) {
6575 mDebugApp = mOrigDebugApp = debugApp;
6576 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
6577 mAlwaysFinishActivities = alwaysFinishActivities;
6578 // This happens before any activities are started, so we can
6579 // change mConfiguration in-place.
6580 mConfiguration.updateFrom(configuration);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08006581 mConfigurationSeq = mConfiguration.seq = 1;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006582 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006583 }
6584 }
6585
6586 public boolean testIsSystemReady() {
6587 // no need to synchronize(this) just to read & return the value
6588 return mSystemReady;
6589 }
6590
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006591 private static File getCalledPreBootReceiversFile() {
6592 File dataDir = Environment.getDataDirectory();
6593 File systemDir = new File(dataDir, "system");
6594 File fname = new File(systemDir, "called_pre_boots.dat");
6595 return fname;
6596 }
Dianne Hackborn661cd522011-08-22 00:26:20 -07006597
6598 static final int LAST_DONE_VERSION = 10000;
6599
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006600 private static ArrayList<ComponentName> readLastDonePreBootReceivers() {
6601 ArrayList<ComponentName> lastDoneReceivers = new ArrayList<ComponentName>();
6602 File file = getCalledPreBootReceiversFile();
6603 FileInputStream fis = null;
6604 try {
6605 fis = new FileInputStream(file);
6606 DataInputStream dis = new DataInputStream(new BufferedInputStream(fis, 2048));
Dianne Hackborn661cd522011-08-22 00:26:20 -07006607 int fvers = dis.readInt();
6608 if (fvers == LAST_DONE_VERSION) {
6609 String vers = dis.readUTF();
6610 String codename = dis.readUTF();
6611 String build = dis.readUTF();
6612 if (android.os.Build.VERSION.RELEASE.equals(vers)
6613 && android.os.Build.VERSION.CODENAME.equals(codename)
6614 && android.os.Build.VERSION.INCREMENTAL.equals(build)) {
6615 int num = dis.readInt();
6616 while (num > 0) {
6617 num--;
6618 String pkg = dis.readUTF();
6619 String cls = dis.readUTF();
6620 lastDoneReceivers.add(new ComponentName(pkg, cls));
6621 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006622 }
6623 }
6624 } catch (FileNotFoundException e) {
6625 } catch (IOException e) {
6626 Slog.w(TAG, "Failure reading last done pre-boot receivers", e);
6627 } finally {
6628 if (fis != null) {
6629 try {
6630 fis.close();
6631 } catch (IOException e) {
6632 }
6633 }
6634 }
6635 return lastDoneReceivers;
6636 }
6637
6638 private static void writeLastDonePreBootReceivers(ArrayList<ComponentName> list) {
6639 File file = getCalledPreBootReceiversFile();
6640 FileOutputStream fos = null;
6641 DataOutputStream dos = null;
6642 try {
6643 Slog.i(TAG, "Writing new set of last done pre-boot receivers...");
6644 fos = new FileOutputStream(file);
6645 dos = new DataOutputStream(new BufferedOutputStream(fos, 2048));
Dianne Hackborn661cd522011-08-22 00:26:20 -07006646 dos.writeInt(LAST_DONE_VERSION);
6647 dos.writeUTF(android.os.Build.VERSION.RELEASE);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006648 dos.writeUTF(android.os.Build.VERSION.CODENAME);
Dianne Hackborn661cd522011-08-22 00:26:20 -07006649 dos.writeUTF(android.os.Build.VERSION.INCREMENTAL);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006650 dos.writeInt(list.size());
6651 for (int i=0; i<list.size(); i++) {
6652 dos.writeUTF(list.get(i).getPackageName());
6653 dos.writeUTF(list.get(i).getClassName());
6654 }
6655 } catch (IOException e) {
6656 Slog.w(TAG, "Failure writing last done pre-boot receivers", e);
6657 file.delete();
6658 } finally {
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07006659 FileUtils.sync(fos);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006660 if (dos != null) {
6661 try {
6662 dos.close();
6663 } catch (IOException e) {
6664 // TODO Auto-generated catch block
6665 e.printStackTrace();
6666 }
6667 }
6668 }
6669 }
6670
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006671 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006672 synchronized(this) {
6673 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006674 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006675 return;
6676 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006677
6678 // Check to see if there are any update receivers to run.
6679 if (!mDidUpdate) {
6680 if (mWaitingUpdate) {
6681 return;
6682 }
6683 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
6684 List<ResolveInfo> ris = null;
6685 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006686 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006687 intent, null, 0);
6688 } catch (RemoteException e) {
6689 }
6690 if (ris != null) {
6691 for (int i=ris.size()-1; i>=0; i--) {
6692 if ((ris.get(i).activityInfo.applicationInfo.flags
6693 &ApplicationInfo.FLAG_SYSTEM) == 0) {
6694 ris.remove(i);
6695 }
6696 }
6697 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006698
6699 ArrayList<ComponentName> lastDoneReceivers = readLastDonePreBootReceivers();
6700
6701 final ArrayList<ComponentName> doneReceivers = new ArrayList<ComponentName>();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006702 for (int i=0; i<ris.size(); i++) {
6703 ActivityInfo ai = ris.get(i).activityInfo;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006704 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6705 if (lastDoneReceivers.contains(comp)) {
6706 ris.remove(i);
6707 i--;
6708 }
6709 }
Dianne Hackborn29aae6f2011-08-18 18:30:09 -07006710
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006711 for (int i=0; i<ris.size(); i++) {
6712 ActivityInfo ai = ris.get(i).activityInfo;
6713 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6714 doneReceivers.add(comp);
6715 intent.setComponent(comp);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006716 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08006717 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006718 finisher = new IIntentReceiver.Stub() {
6719 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07006720 String data, Bundle extras, boolean ordered,
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006721 boolean sticky) {
6722 // The raw IIntentReceiver interface is called
6723 // with the AM lock held, so redispatch to
6724 // execute our code without the lock.
6725 mHandler.post(new Runnable() {
6726 public void run() {
6727 synchronized (ActivityManagerService.this) {
6728 mDidUpdate = true;
6729 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006730 writeLastDonePreBootReceivers(doneReceivers);
Dianne Hackborn661cd522011-08-22 00:26:20 -07006731 showBootMessage(mContext.getText(
6732 R.string.android_upgrading_complete),
6733 false);
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006734 systemReady(goingCallback);
6735 }
6736 });
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006737 }
6738 };
6739 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006740 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006741 broadcastIntentLocked(null, null, intent, null, finisher,
6742 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08006743 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006744 mWaitingUpdate = true;
6745 }
6746 }
6747 }
6748 if (mWaitingUpdate) {
6749 return;
6750 }
6751 mDidUpdate = true;
6752 }
6753
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006754 mSystemReady = true;
6755 if (!mStartRunning) {
6756 return;
6757 }
6758 }
6759
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006760 ArrayList<ProcessRecord> procsToKill = null;
6761 synchronized(mPidsSelfLocked) {
6762 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
6763 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
6764 if (!isAllowedWhileBooting(proc.info)){
6765 if (procsToKill == null) {
6766 procsToKill = new ArrayList<ProcessRecord>();
6767 }
6768 procsToKill.add(proc);
6769 }
6770 }
6771 }
6772
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006773 synchronized(this) {
6774 if (procsToKill != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006775 for (int i=procsToKill.size()-1; i>=0; i--) {
6776 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08006777 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborn130b0d22011-07-26 22:07:48 -07006778 removeProcessLocked(proc, true, false);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006779 }
6780 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006781
6782 // Now that we have cleaned up any update processes, we
6783 // are ready to start launching real processes and know that
6784 // we won't trample on them any more.
6785 mProcessesReady = true;
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006786 }
6787
Joe Onorato8a9b2202010-02-26 18:56:32 -08006788 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006789 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006790 SystemClock.uptimeMillis());
6791
6792 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006793 // Make sure we have no pre-ready processes sitting around.
6794
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006795 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
6796 ResolveInfo ri = mContext.getPackageManager()
6797 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07006798 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006799 CharSequence errorMsg = null;
6800 if (ri != null) {
6801 ActivityInfo ai = ri.activityInfo;
6802 ApplicationInfo app = ai.applicationInfo;
6803 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
6804 mTopAction = Intent.ACTION_FACTORY_TEST;
6805 mTopData = null;
6806 mTopComponent = new ComponentName(app.packageName,
6807 ai.name);
6808 } else {
6809 errorMsg = mContext.getResources().getText(
6810 com.android.internal.R.string.factorytest_not_system);
6811 }
6812 } else {
6813 errorMsg = mContext.getResources().getText(
6814 com.android.internal.R.string.factorytest_no_action);
6815 }
6816 if (errorMsg != null) {
6817 mTopAction = null;
6818 mTopData = null;
6819 mTopComponent = null;
6820 Message msg = Message.obtain();
6821 msg.what = SHOW_FACTORY_ERROR_MSG;
6822 msg.getData().putCharSequence("msg", errorMsg);
6823 mHandler.sendMessage(msg);
6824 }
6825 }
6826 }
6827
6828 retrieveSettings();
6829
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006830 if (goingCallback != null) goingCallback.run();
6831
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006832 synchronized (this) {
6833 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
6834 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006835 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07006836 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006837 if (apps != null) {
6838 int N = apps.size();
6839 int i;
6840 for (i=0; i<N; i++) {
6841 ApplicationInfo info
6842 = (ApplicationInfo)apps.get(i);
6843 if (info != null &&
6844 !info.packageName.equals("android")) {
6845 addAppLocked(info);
6846 }
6847 }
6848 }
6849 } catch (RemoteException ex) {
6850 // pm is in same process, this will never happen.
6851 }
6852 }
6853
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006854 // Start up initial activity.
6855 mBooting = true;
6856
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006857 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006858 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006859 Message msg = Message.obtain();
6860 msg.what = SHOW_UID_ERROR_MSG;
6861 mHandler.sendMessage(msg);
6862 }
6863 } catch (RemoteException e) {
6864 }
6865
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006866 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006867 }
6868 }
6869
Dan Egnorb7f03672009-12-09 16:22:32 -08006870 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006871 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006872 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006873 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006874 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006875 startAppProblemLocked(app);
6876 app.stopFreezingAllLocked();
6877 return handleAppCrashLocked(app);
6878 }
6879
Dan Egnorb7f03672009-12-09 16:22:32 -08006880 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006881 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006882 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08006883 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08006884 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
6885 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006886 startAppProblemLocked(app);
6887 app.stopFreezingAllLocked();
6888 }
6889
6890 /**
6891 * Generate a process error record, suitable for attachment to a ProcessRecord.
6892 *
6893 * @param app The ProcessRecord in which the error occurred.
6894 * @param condition Crashing, Application Not Responding, etc. Values are defined in
6895 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08006896 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006897 * @param shortMsg Short message describing the crash.
6898 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08006899 * @param stackTrace Full crash stack trace, may be null.
6900 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006901 * @return Returns a fully-formed AppErrorStateInfo record.
6902 */
6903 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08006904 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006905 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08006906
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006907 report.condition = condition;
6908 report.processName = app.processName;
6909 report.pid = app.pid;
6910 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08006911 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006912 report.shortMsg = shortMsg;
6913 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08006914 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006915
6916 return report;
6917 }
6918
Dan Egnor42471dd2010-01-07 17:25:22 -08006919 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006920 synchronized (this) {
6921 app.crashing = false;
6922 app.crashingReport = null;
6923 app.notResponding = false;
6924 app.notRespondingReport = null;
6925 if (app.anrDialog == fromDialog) {
6926 app.anrDialog = null;
6927 }
6928 if (app.waitDialog == fromDialog) {
6929 app.waitDialog = null;
6930 }
6931 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08006932 handleAppCrashLocked(app);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07006933 Slog.i(ActivityManagerService.TAG, "Killing " + app + ": user's request");
Dianne Hackborn8633e682010-04-22 16:03:41 -07006934 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
6935 app.processName, app.setAdj, "user's request after error");
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07006936 Process.killProcessQuiet(app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006937 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006938 }
6939 }
Dan Egnor42471dd2010-01-07 17:25:22 -08006940
Dan Egnorb7f03672009-12-09 16:22:32 -08006941 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006942 long now = SystemClock.uptimeMillis();
6943
6944 Long crashTime = mProcessCrashTimes.get(app.info.processName,
6945 app.info.uid);
Dianne Hackborn7d608422011-08-07 16:24:18 -07006946 if (crashTime != null && now < crashTime+ProcessList.MIN_CRASH_INTERVAL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006947 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08006948 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006949 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006950 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006951 app.info.processName, app.info.uid);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006952 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
6953 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006954 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006955 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006956 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006957 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006958 }
6959 }
6960 if (!app.persistent) {
6961 // We don't want to start this process again until the user
6962 // explicitly does so... but for persistent process, we really
6963 // need to keep it running. If a persistent process is actually
6964 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08006965 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006966 app.info.processName);
6967 mBadProcesses.put(app.info.processName, app.info.uid, now);
6968 app.bad = true;
6969 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
6970 app.removed = true;
Dianne Hackborn130b0d22011-07-26 22:07:48 -07006971 // Don't let services in this process be restarted and potentially
6972 // annoy the user repeatedly. Unless it is persistent, since those
6973 // processes run critical code.
6974 removeProcessLocked(app, false, false);
Dianne Hackborncb44d962011-03-10 17:02:27 -08006975 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006976 return false;
6977 }
Dianne Hackborncb44d962011-03-10 17:02:27 -08006978 mMainStack.resumeTopActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006979 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006980 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006981 if (r.app == app) {
6982 // If the top running activity is from this crashing
6983 // process, then terminate it to avoid getting in a loop.
6984 Slog.w(TAG, " Force finishing activity "
6985 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006986 int index = mMainStack.indexOfTokenLocked(r);
6987 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006988 Activity.RESULT_CANCELED, null, "crashed");
Dianne Hackborn070783f2010-12-29 16:46:28 -08006989 // Also terminate any activities below it that aren't yet
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006990 // stopped, to avoid a situation where one will get
6991 // re-start our crashing activity once it gets resumed again.
6992 index--;
6993 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006994 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006995 if (r.state == ActivityState.RESUMED
6996 || r.state == ActivityState.PAUSING
6997 || r.state == ActivityState.PAUSED) {
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -08006998 if (!r.isHomeActivity || mHomeProcess != r.app) {
Dianne Hackbornf83c5552010-03-31 22:19:32 -07006999 Slog.w(TAG, " Force finishing activity "
7000 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007001 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07007002 Activity.RESULT_CANCELED, null, "crashed");
7003 }
7004 }
7005 }
7006 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007007 }
7008
7009 // Bump up the crash count of any services currently running in the proc.
7010 if (app.services.size() != 0) {
7011 // Any services running in the application need to be placed
7012 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07007013 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007014 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007015 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007016 sr.crashCount++;
7017 }
7018 }
Mattias Larssona4fd0072010-06-22 22:37:03 +02007019
7020 // If the crashing process is what we consider to be the "home process" and it has been
7021 // replaced by a third-party app, clear the package preferred activities from packages
7022 // with a home activity running in the process to prevent a repeatedly crashing app
7023 // from blocking the user to manually clear the list.
7024 if (app == mHomeProcess && mHomeProcess.activities.size() > 0
7025 && (mHomeProcess.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
7026 Iterator it = mHomeProcess.activities.iterator();
7027 while (it.hasNext()) {
Jean-Baptiste Queru5ea89f72010-07-30 09:30:31 -07007028 ActivityRecord r = (ActivityRecord)it.next();
Mattias Larssona4fd0072010-06-22 22:37:03 +02007029 if (r.isHomeActivity) {
7030 Log.i(TAG, "Clearing package preferred activities from " + r.packageName);
7031 try {
7032 ActivityThread.getPackageManager()
7033 .clearPackagePreferredActivities(r.packageName);
7034 } catch (RemoteException c) {
7035 // pm is in same process, this will never happen.
7036 }
7037 }
7038 }
7039 }
7040
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007041 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
7042 return true;
7043 }
7044
7045 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08007046 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
7047 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007048 skipCurrentReceiverLocked(app);
7049 }
7050
7051 void skipCurrentReceiverLocked(ProcessRecord app) {
7052 boolean reschedule = false;
7053 BroadcastRecord r = app.curReceiver;
7054 if (r != null) {
7055 // The current broadcast is waiting for this app's receiver
7056 // to be finished. Looks like that's not going to happen, so
7057 // let the broadcast continue.
Jeff Brown4d94a762010-09-23 11:33:28 -07007058 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007059 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
7060 r.resultExtras, r.resultAbort, true);
7061 reschedule = true;
7062 }
7063 r = mPendingBroadcast;
7064 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007065 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007066 "skip & discard pending app " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -07007067 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007068 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
7069 r.resultExtras, r.resultAbort, true);
7070 reschedule = true;
7071 }
7072 if (reschedule) {
7073 scheduleBroadcastsLocked();
7074 }
7075 }
7076
Dan Egnor60d87622009-12-16 16:32:58 -08007077 /**
7078 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
7079 * The application process will exit immediately after this call returns.
7080 * @param app object of the crashing app, null for the system server
7081 * @param crashInfo describing the exception
7082 */
7083 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
Dianne Hackborncb44d962011-03-10 17:02:27 -08007084 ProcessRecord r = findAppProcess(app, "Crash");
Dan Egnor60d87622009-12-16 16:32:58 -08007085
7086 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
7087 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08007088 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08007089 crashInfo.exceptionClassName,
7090 crashInfo.exceptionMessage,
7091 crashInfo.throwFileName,
7092 crashInfo.throwLineNumber);
7093
Dan Egnor42471dd2010-01-07 17:25:22 -08007094 addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08007095
7096 crashApplication(r, crashInfo);
7097 }
7098
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07007099 public void handleApplicationStrictModeViolation(
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007100 IBinder app,
7101 int violationMask,
7102 StrictMode.ViolationInfo info) {
Dianne Hackborncb44d962011-03-10 17:02:27 -08007103 ProcessRecord r = findAppProcess(app, "StrictMode");
7104 if (r == null) {
7105 return;
7106 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07007107
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07007108 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -08007109 Integer stackFingerprint = info.hashCode();
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07007110 boolean logIt = true;
7111 synchronized (mAlreadyLoggedViolatedStacks) {
7112 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
7113 logIt = false;
7114 // TODO: sub-sample into EventLog for these, with
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007115 // the info.durationMillis? Then we'd get
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07007116 // the relative pain numbers, without logging all
7117 // the stack traces repeatedly. We'd want to do
7118 // likewise in the client code, which also does
7119 // dup suppression, before the Binder call.
7120 } else {
7121 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
7122 mAlreadyLoggedViolatedStacks.clear();
7123 }
7124 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
7125 }
7126 }
7127 if (logIt) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007128 logStrictModeViolationToDropBox(r, info);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07007129 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07007130 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07007131
7132 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
7133 AppErrorResult result = new AppErrorResult();
7134 synchronized (this) {
7135 final long origId = Binder.clearCallingIdentity();
7136
7137 Message msg = Message.obtain();
7138 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
7139 HashMap<String, Object> data = new HashMap<String, Object>();
7140 data.put("result", result);
7141 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07007142 data.put("violationMask", violationMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007143 data.put("info", info);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07007144 msg.obj = data;
7145 mHandler.sendMessage(msg);
7146
7147 Binder.restoreCallingIdentity(origId);
7148 }
7149 int res = result.get();
Dianne Hackbornb424b632010-08-18 15:59:05 -07007150 Slog.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07007151 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07007152 }
7153
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007154 // Depending on the policy in effect, there could be a bunch of
7155 // these in quick succession so we try to batch these together to
7156 // minimize disk writes, number of dropbox entries, and maximize
7157 // compression, by having more fewer, larger records.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007158 private void logStrictModeViolationToDropBox(
7159 ProcessRecord process,
7160 StrictMode.ViolationInfo info) {
7161 if (info == null) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007162 return;
7163 }
7164 final boolean isSystemApp = process == null ||
7165 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
7166 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
7167 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
7168 final DropBoxManager dbox = (DropBoxManager)
7169 mContext.getSystemService(Context.DROPBOX_SERVICE);
7170
7171 // Exit early if the dropbox isn't configured to accept this report type.
7172 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
7173
7174 boolean bufferWasEmpty;
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007175 boolean needsFlush;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007176 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
7177 synchronized (sb) {
7178 bufferWasEmpty = sb.length() == 0;
7179 appendDropBoxProcessHeaders(process, sb);
7180 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
7181 sb.append("System-App: ").append(isSystemApp).append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007182 sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
7183 if (info.violationNumThisLoop != 0) {
7184 sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
7185 }
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07007186 if (info.numAnimationsRunning != 0) {
7187 sb.append("Animations-Running: ").append(info.numAnimationsRunning).append("\n");
7188 }
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07007189 if (info.broadcastIntentAction != null) {
7190 sb.append("Broadcast-Intent-Action: ").append(info.broadcastIntentAction).append("\n");
7191 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08007192 if (info.durationMillis != -1) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007193 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007194 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08007195 if (info.numInstances != -1) {
7196 sb.append("Instance-Count: ").append(info.numInstances).append("\n");
7197 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08007198 if (info.tags != null) {
7199 for (String tag : info.tags) {
7200 sb.append("Span-Tag: ").append(tag).append("\n");
7201 }
7202 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007203 sb.append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007204 if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
7205 sb.append(info.crashInfo.stackTrace);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007206 }
7207 sb.append("\n");
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007208
7209 // Only buffer up to ~64k. Various logging bits truncate
7210 // things at 128k.
7211 needsFlush = (sb.length() > 64 * 1024);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007212 }
7213
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007214 // Flush immediately if the buffer's grown too large, or this
7215 // is a non-system app. Non-system apps are isolated with a
7216 // different tag & policy and not batched.
7217 //
7218 // Batching is useful during internal testing with
7219 // StrictMode settings turned up high. Without batching,
7220 // thousands of separate files could be created on boot.
7221 if (!isSystemApp || needsFlush) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007222 new Thread("Error dump: " + dropboxTag) {
7223 @Override
7224 public void run() {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007225 String report;
7226 synchronized (sb) {
7227 report = sb.toString();
7228 sb.delete(0, sb.length());
7229 sb.trimToSize();
7230 }
7231 if (report.length() != 0) {
7232 dbox.addText(dropboxTag, report);
7233 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007234 }
7235 }.start();
7236 return;
7237 }
7238
7239 // System app batching:
7240 if (!bufferWasEmpty) {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007241 // An existing dropbox-writing thread is outstanding, so
7242 // we don't need to start it up. The existing thread will
7243 // catch the buffer appends we just did.
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007244 return;
7245 }
7246
7247 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
7248 // (After this point, we shouldn't access AMS internal data structures.)
7249 new Thread("Error dump: " + dropboxTag) {
7250 @Override
7251 public void run() {
7252 // 5 second sleep to let stacks arrive and be batched together
7253 try {
7254 Thread.sleep(5000); // 5 seconds
7255 } catch (InterruptedException e) {}
7256
7257 String errorReport;
7258 synchronized (mStrictModeBuffer) {
7259 errorReport = mStrictModeBuffer.toString();
7260 if (errorReport.length() == 0) {
7261 return;
7262 }
7263 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
7264 mStrictModeBuffer.trimToSize();
7265 }
7266 dbox.addText(dropboxTag, errorReport);
7267 }
7268 }.start();
7269 }
7270
Dan Egnor60d87622009-12-16 16:32:58 -08007271 /**
7272 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
7273 * @param app object of the crashing app, null for the system server
7274 * @param tag reported by the caller
7275 * @param crashInfo describing the context of the error
7276 * @return true if the process should exit immediately (WTF is fatal)
7277 */
7278 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08007279 ApplicationErrorReport.CrashInfo crashInfo) {
Dianne Hackborncb44d962011-03-10 17:02:27 -08007280 ProcessRecord r = findAppProcess(app, "WTF");
Dan Egnor60d87622009-12-16 16:32:58 -08007281
7282 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
7283 app == null ? "system" : (r == null ? "unknown" : r.processName),
Dan Egnor2780e732010-01-22 14:47:35 -08007284 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08007285 tag, crashInfo.exceptionMessage);
7286
Dan Egnor42471dd2010-01-07 17:25:22 -08007287 addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08007288
Dianne Hackborn1ab43772011-03-15 14:38:02 -07007289 if (r != null && r.pid != Process.myPid() &&
7290 Settings.Secure.getInt(mContext.getContentResolver(),
7291 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08007292 crashApplication(r, crashInfo);
7293 return true;
7294 } else {
7295 return false;
7296 }
7297 }
7298
7299 /**
7300 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
7301 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
7302 */
Dianne Hackborncb44d962011-03-10 17:02:27 -08007303 private ProcessRecord findAppProcess(IBinder app, String reason) {
Dan Egnor60d87622009-12-16 16:32:58 -08007304 if (app == null) {
7305 return null;
7306 }
7307
7308 synchronized (this) {
7309 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
7310 final int NA = apps.size();
7311 for (int ia=0; ia<NA; ia++) {
7312 ProcessRecord p = apps.valueAt(ia);
7313 if (p.thread != null && p.thread.asBinder() == app) {
7314 return p;
7315 }
7316 }
7317 }
7318
Dianne Hackborncb44d962011-03-10 17:02:27 -08007319 Slog.w(TAG, "Can't find mystery application for " + reason
7320 + " from pid=" + Binder.getCallingPid()
7321 + " uid=" + Binder.getCallingUid() + ": " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08007322 return null;
7323 }
7324 }
7325
7326 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007327 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
7328 * to append various headers to the dropbox log text.
Dan Egnor60d87622009-12-16 16:32:58 -08007329 */
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07007330 private void appendDropBoxProcessHeaders(ProcessRecord process, StringBuilder sb) {
Vairavan Srinivasan68a4e0a2011-02-14 20:45:59 -08007331 // Watchdog thread ends up invoking this function (with
7332 // a null ProcessRecord) to add the stack file to dropbox.
7333 // Do not acquire a lock on this (am) in such cases, as it
7334 // could cause a potential deadlock, if and when watchdog
7335 // is invoked due to unavailability of lock on am and it
7336 // would prevent watchdog from killing system_server.
7337 if (process == null) {
7338 sb.append("Process: system_server\n");
7339 return;
7340 }
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07007341 // Note: ProcessRecord 'process' is guarded by the service
7342 // instance. (notably process.pkgList, which could otherwise change
7343 // concurrently during execution of this method)
7344 synchronized (this) {
Vairavan Srinivasan68a4e0a2011-02-14 20:45:59 -08007345 if (process.pid == MY_PID) {
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07007346 sb.append("Process: system_server\n");
7347 } else {
7348 sb.append("Process: ").append(process.processName).append("\n");
7349 }
Dan Egnora455d192010-03-12 08:52:28 -08007350 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007351 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08007352 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
7353 for (String pkg : process.pkgList) {
7354 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08007355 try {
Dan Egnora455d192010-03-12 08:52:28 -08007356 PackageInfo pi = pm.getPackageInfo(pkg, 0);
7357 if (pi != null) {
7358 sb.append(" v").append(pi.versionCode);
7359 if (pi.versionName != null) {
7360 sb.append(" (").append(pi.versionName).append(")");
7361 }
7362 }
7363 } catch (RemoteException e) {
7364 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08007365 }
Dan Egnora455d192010-03-12 08:52:28 -08007366 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08007367 }
Dan Egnora455d192010-03-12 08:52:28 -08007368 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007369 }
7370
7371 private static String processClass(ProcessRecord process) {
7372 if (process == null || process.pid == MY_PID) {
7373 return "system_server";
7374 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
7375 return "system_app";
7376 } else {
7377 return "data_app";
7378 }
7379 }
7380
7381 /**
7382 * Write a description of an error (crash, WTF, ANR) to the drop box.
7383 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
7384 * @param process which caused the error, null means the system server
7385 * @param activity which triggered the error, null if unknown
7386 * @param parent activity related to the error, null if unknown
7387 * @param subject line related to the error, null if absent
7388 * @param report in long form describing the error, null if absent
7389 * @param logFile to include in the report, null if none
7390 * @param crashInfo giving an application stack trace, null if absent
7391 */
7392 public void addErrorToDropBox(String eventType,
7393 ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
7394 final String report, final File logFile,
7395 final ApplicationErrorReport.CrashInfo crashInfo) {
7396 // NOTE -- this must never acquire the ActivityManagerService lock,
7397 // otherwise the watchdog may be prevented from resetting the system.
7398
7399 final String dropboxTag = processClass(process) + "_" + eventType;
7400 final DropBoxManager dbox = (DropBoxManager)
7401 mContext.getSystemService(Context.DROPBOX_SERVICE);
7402
7403 // Exit early if the dropbox isn't configured to accept this report type.
7404 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
7405
7406 final StringBuilder sb = new StringBuilder(1024);
7407 appendDropBoxProcessHeaders(process, sb);
Dan Egnora455d192010-03-12 08:52:28 -08007408 if (activity != null) {
7409 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
7410 }
7411 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
7412 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
7413 }
7414 if (parent != null && parent != activity) {
7415 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
7416 }
7417 if (subject != null) {
7418 sb.append("Subject: ").append(subject).append("\n");
7419 }
7420 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
Christian Lindeberg03d2ca62010-09-28 14:52:20 +02007421 if (Debug.isDebuggerConnected()) {
7422 sb.append("Debugger: Connected\n");
7423 }
Dan Egnora455d192010-03-12 08:52:28 -08007424 sb.append("\n");
7425
7426 // Do the rest in a worker thread to avoid blocking the caller on I/O
7427 // (After this point, we shouldn't access AMS internal data structures.)
7428 Thread worker = new Thread("Error dump: " + dropboxTag) {
7429 @Override
7430 public void run() {
7431 if (report != null) {
7432 sb.append(report);
7433 }
7434 if (logFile != null) {
7435 try {
7436 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
7437 } catch (IOException e) {
7438 Slog.e(TAG, "Error reading " + logFile, e);
7439 }
7440 }
7441 if (crashInfo != null && crashInfo.stackTrace != null) {
7442 sb.append(crashInfo.stackTrace);
7443 }
7444
7445 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
7446 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
7447 if (lines > 0) {
7448 sb.append("\n");
7449
7450 // Merge several logcat streams, and take the last N lines
7451 InputStreamReader input = null;
7452 try {
7453 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
7454 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
7455 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
7456
7457 try { logcat.getOutputStream().close(); } catch (IOException e) {}
7458 try { logcat.getErrorStream().close(); } catch (IOException e) {}
7459 input = new InputStreamReader(logcat.getInputStream());
7460
7461 int num;
7462 char[] buf = new char[8192];
7463 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
7464 } catch (IOException e) {
7465 Slog.e(TAG, "Error running logcat", e);
7466 } finally {
7467 if (input != null) try { input.close(); } catch (IOException e) {}
7468 }
7469 }
7470
7471 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08007472 }
Dan Egnora455d192010-03-12 08:52:28 -08007473 };
7474
7475 if (process == null || process.pid == MY_PID) {
7476 worker.run(); // We may be about to die -- need to run this synchronously
7477 } else {
7478 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08007479 }
7480 }
7481
7482 /**
7483 * Bring up the "unexpected error" dialog box for a crashing app.
7484 * Deal with edge cases (intercepts from instrumented applications,
7485 * ActivityController, error intent receivers, that sort of thing).
7486 * @param r the application crashing
7487 * @param crashInfo describing the failure
7488 */
7489 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007490 long timeMillis = System.currentTimeMillis();
7491 String shortMsg = crashInfo.exceptionClassName;
7492 String longMsg = crashInfo.exceptionMessage;
7493 String stackTrace = crashInfo.stackTrace;
7494 if (shortMsg != null && longMsg != null) {
7495 longMsg = shortMsg + ": " + longMsg;
7496 } else if (shortMsg != null) {
7497 longMsg = shortMsg;
7498 }
7499
Dan Egnor60d87622009-12-16 16:32:58 -08007500 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007501 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007502 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007503 try {
7504 String name = r != null ? r.processName : null;
7505 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08007506 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08007507 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007508 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007509 + " at watcher's request");
7510 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08007511 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007512 }
7513 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007514 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007515 }
7516 }
7517
7518 final long origId = Binder.clearCallingIdentity();
7519
7520 // If this process is running instrumentation, finish it.
7521 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007522 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007523 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08007524 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
7525 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007526 Bundle info = new Bundle();
7527 info.putString("shortMsg", shortMsg);
7528 info.putString("longMsg", longMsg);
7529 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
7530 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007531 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007532 }
7533
Dan Egnor60d87622009-12-16 16:32:58 -08007534 // If we can't identify the process or it's already exceeded its crash quota,
7535 // quit right away without showing a crash dialog.
7536 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007537 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007538 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007539 }
7540
7541 Message msg = Message.obtain();
7542 msg.what = SHOW_ERROR_MSG;
7543 HashMap data = new HashMap();
7544 data.put("result", result);
7545 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007546 msg.obj = data;
7547 mHandler.sendMessage(msg);
7548
7549 Binder.restoreCallingIdentity(origId);
7550 }
7551
7552 int res = result.get();
7553
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007554 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007555 synchronized (this) {
7556 if (r != null) {
7557 mProcessCrashTimes.put(r.info.processName, r.info.uid,
7558 SystemClock.uptimeMillis());
7559 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007560 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007561 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007562 }
7563 }
7564
7565 if (appErrorIntent != null) {
7566 try {
7567 mContext.startActivity(appErrorIntent);
7568 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007569 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007570 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007571 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007572 }
Dan Egnorb7f03672009-12-09 16:22:32 -08007573
7574 Intent createAppErrorIntentLocked(ProcessRecord r,
7575 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
7576 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007577 if (report == null) {
7578 return null;
7579 }
7580 Intent result = new Intent(Intent.ACTION_APP_ERROR);
7581 result.setComponent(r.errorReportReceiver);
7582 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
7583 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
7584 return result;
7585 }
7586
Dan Egnorb7f03672009-12-09 16:22:32 -08007587 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
7588 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007589 if (r.errorReportReceiver == null) {
7590 return null;
7591 }
7592
7593 if (!r.crashing && !r.notResponding) {
7594 return null;
7595 }
7596
Dan Egnorb7f03672009-12-09 16:22:32 -08007597 ApplicationErrorReport report = new ApplicationErrorReport();
7598 report.packageName = r.info.packageName;
7599 report.installerPackageName = r.errorReportReceiver.getPackageName();
7600 report.processName = r.processName;
7601 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01007602 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007603
Dan Egnorb7f03672009-12-09 16:22:32 -08007604 if (r.crashing) {
7605 report.type = ApplicationErrorReport.TYPE_CRASH;
7606 report.crashInfo = crashInfo;
7607 } else if (r.notResponding) {
7608 report.type = ApplicationErrorReport.TYPE_ANR;
7609 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007610
Dan Egnorb7f03672009-12-09 16:22:32 -08007611 report.anrInfo.activity = r.notRespondingReport.tag;
7612 report.anrInfo.cause = r.notRespondingReport.shortMsg;
7613 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007614 }
7615
Dan Egnorb7f03672009-12-09 16:22:32 -08007616 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007617 }
7618
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007619 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
7620 // assume our apps are happy - lazy create the list
7621 List<ActivityManager.ProcessErrorStateInfo> errList = null;
7622
7623 synchronized (this) {
7624
7625 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007626 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7627 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007628 if ((app.thread != null) && (app.crashing || app.notResponding)) {
7629 // This one's in trouble, so we'll generate a report for it
7630 // crashes are higher priority (in case there's a crash *and* an anr)
7631 ActivityManager.ProcessErrorStateInfo report = null;
7632 if (app.crashing) {
7633 report = app.crashingReport;
7634 } else if (app.notResponding) {
7635 report = app.notRespondingReport;
7636 }
7637
7638 if (report != null) {
7639 if (errList == null) {
7640 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
7641 }
7642 errList.add(report);
7643 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007644 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007645 " crashing = " + app.crashing +
7646 " notResponding = " + app.notResponding);
7647 }
7648 }
7649 }
7650 }
7651
7652 return errList;
7653 }
Dianne Hackborn905577f2011-09-07 18:31:28 -07007654
7655 static int oomAdjToImportance(int adj, ActivityManager.RunningAppProcessInfo currApp) {
7656 if (adj >= ProcessList.EMPTY_APP_ADJ) {
7657 return ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
7658 } else if (adj >= ProcessList.HIDDEN_APP_MIN_ADJ) {
7659 if (currApp != null) {
7660 currApp.lru = adj - ProcessList.HIDDEN_APP_MIN_ADJ + 1;
7661 }
7662 return ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
7663 } else if (adj >= ProcessList.HOME_APP_ADJ) {
7664 if (currApp != null) {
7665 currApp.lru = 0;
7666 }
7667 return ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
7668 } else if (adj >= ProcessList.SECONDARY_SERVER_ADJ) {
7669 return ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
7670 } else if (adj >= ProcessList.HEAVY_WEIGHT_APP_ADJ) {
7671 return ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE;
7672 } else if (adj >= ProcessList.PERCEPTIBLE_APP_ADJ) {
7673 return ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
7674 } else if (adj >= ProcessList.VISIBLE_APP_ADJ) {
7675 return ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
7676 } else {
7677 return ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
7678 }
7679 }
7680
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007681 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
7682 // Lazy instantiation of list
7683 List<ActivityManager.RunningAppProcessInfo> runList = null;
7684 synchronized (this) {
7685 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007686 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7687 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007688 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
7689 // Generate process state info for running application
7690 ActivityManager.RunningAppProcessInfo currApp =
7691 new ActivityManager.RunningAppProcessInfo(app.processName,
7692 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07007693 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007694 if (mHeavyWeightProcess == app) {
Dianne Hackborn482566e2010-09-03 12:51:28 -07007695 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007696 }
Dianne Hackborn42499172010-10-15 18:45:07 -07007697 if (app.persistent) {
7698 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_PERSISTENT;
7699 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007700 int adj = app.curAdj;
Dianne Hackborn905577f2011-09-07 18:31:28 -07007701 currApp.importance = oomAdjToImportance(adj, currApp);
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007702 currApp.importanceReasonCode = app.adjTypeCode;
7703 if (app.adjSource instanceof ProcessRecord) {
7704 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn905577f2011-09-07 18:31:28 -07007705 currApp.importanceReasonImportance = oomAdjToImportance(
7706 app.adjSourceOom, null);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007707 } else if (app.adjSource instanceof ActivityRecord) {
7708 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007709 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
7710 }
7711 if (app.adjTarget instanceof ComponentName) {
7712 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
7713 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007714 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007715 // + " lru=" + currApp.lru);
7716 if (runList == null) {
7717 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
7718 }
7719 runList.add(currApp);
7720 }
7721 }
7722 }
7723 return runList;
7724 }
7725
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007726 public List<ApplicationInfo> getRunningExternalApplications() {
7727 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
7728 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
7729 if (runningApps != null && runningApps.size() > 0) {
7730 Set<String> extList = new HashSet<String>();
7731 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
7732 if (app.pkgList != null) {
7733 for (String pkg : app.pkgList) {
7734 extList.add(pkg);
7735 }
7736 }
7737 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007738 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007739 for (String pkg : extList) {
7740 try {
7741 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
7742 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
7743 retList.add(info);
7744 }
7745 } catch (RemoteException e) {
7746 }
7747 }
7748 }
7749 return retList;
7750 }
7751
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007752 @Override
7753 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007754 if (checkCallingPermission(android.Manifest.permission.DUMP)
7755 != PackageManager.PERMISSION_GRANTED) {
7756 pw.println("Permission Denial: can't dump ActivityManager from from pid="
7757 + Binder.getCallingPid()
7758 + ", uid=" + Binder.getCallingUid()
7759 + " without permission "
7760 + android.Manifest.permission.DUMP);
7761 return;
7762 }
7763
7764 boolean dumpAll = false;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007765 boolean dumpClient = false;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007766
7767 int opti = 0;
7768 while (opti < args.length) {
7769 String opt = args[opti];
7770 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
7771 break;
7772 }
7773 opti++;
7774 if ("-a".equals(opt)) {
7775 dumpAll = true;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007776 } else if ("-c".equals(opt)) {
7777 dumpClient = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007778 } else if ("-h".equals(opt)) {
7779 pw.println("Activity manager dump options:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007780 pw.println(" [-a] [-c] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007781 pw.println(" cmd may be one of:");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007782 pw.println(" a[ctivities]: activity stack state");
7783 pw.println(" b[roadcasts]: broadcast state");
7784 pw.println(" i[ntents]: pending intent state");
7785 pw.println(" p[rocesses]: process state");
7786 pw.println(" o[om]: out of memory management");
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07007787 pw.println(" prov[iders] [COMP_SPEC ...]: content provider state");
7788 pw.println(" s[ervices] [COMP_SPEC ...]: service state");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007789 pw.println(" service [COMP_SPEC]: service client-side state");
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07007790 pw.println(" all: dump all activities");
7791 pw.println(" top: dump the top activity");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007792 pw.println(" cmd may also be a COMP_SPEC to dump activities.");
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07007793 pw.println(" COMP_SPEC may be a component name (com.foo/.myApp),");
7794 pw.println(" a partial substring in a component name, a");
7795 pw.println(" hex object identifier.");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007796 pw.println(" -a: include all available server state.");
7797 pw.println(" -c: include client state.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007798 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007799 } else {
7800 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007801 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007802 }
7803
7804 // Is the caller requesting to dump a particular piece of data?
7805 if (opti < args.length) {
7806 String cmd = args[opti];
7807 opti++;
7808 if ("activities".equals(cmd) || "a".equals(cmd)) {
7809 synchronized (this) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007810 dumpActivitiesLocked(fd, pw, args, opti, true, dumpClient);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007811 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007812 return;
7813 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
7814 synchronized (this) {
7815 dumpBroadcastsLocked(fd, pw, args, opti, true);
7816 }
7817 return;
7818 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
7819 synchronized (this) {
7820 dumpPendingIntentsLocked(fd, pw, args, opti, true);
7821 }
7822 return;
7823 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
7824 synchronized (this) {
7825 dumpProcessesLocked(fd, pw, args, opti, true);
7826 }
7827 return;
Dianne Hackborn287952c2010-09-22 22:34:31 -07007828 } else if ("oom".equals(cmd) || "o".equals(cmd)) {
7829 synchronized (this) {
7830 dumpOomLocked(fd, pw, args, opti, true);
7831 }
7832 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007833 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
7834 synchronized (this) {
7835 dumpProvidersLocked(fd, pw, args, opti, true);
7836 }
7837 return;
7838 } else if ("service".equals(cmd)) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007839 String[] newArgs;
7840 String name;
7841 if (opti >= args.length) {
7842 name = null;
7843 newArgs = EMPTY_STRING_ARRAY;
7844 } else {
7845 name = args[opti];
7846 opti++;
7847 newArgs = new String[args.length - opti];
7848 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
7849 }
7850 if (!dumpService(fd, pw, name, newArgs, 0, dumpAll)) {
7851 pw.println("No services match: " + name);
7852 pw.println("Use -h for help.");
7853 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007854 return;
7855 } else if ("services".equals(cmd) || "s".equals(cmd)) {
7856 synchronized (this) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007857 dumpServicesLocked(fd, pw, args, opti, true, dumpClient);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007858 }
7859 return;
Dianne Hackborn625ac272010-09-17 18:29:22 -07007860 } else {
7861 // Dumping a single activity?
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007862 if (!dumpActivity(fd, pw, cmd, args, opti, dumpAll)) {
7863 pw.println("Bad activity command, or no activities match: " + cmd);
7864 pw.println("Use -h for help.");
Dianne Hackborn625ac272010-09-17 18:29:22 -07007865 }
Dianne Hackborn30d71892010-12-11 10:37:55 -08007866 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007867 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007868 }
7869
7870 // No piece of data specified, dump everything.
7871 synchronized (this) {
7872 boolean needSep;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007873 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007874 if (needSep) {
7875 pw.println(" ");
7876 }
7877 if (dumpAll) {
7878 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007879 }
7880 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll);
7881 if (needSep) {
7882 pw.println(" ");
7883 }
7884 if (dumpAll) {
7885 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007886 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007887 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007888 if (needSep) {
7889 pw.println(" ");
7890 }
7891 if (dumpAll) {
7892 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007893 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007894 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll, dumpClient);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007895 if (needSep) {
7896 pw.println(" ");
7897 }
7898 if (dumpAll) {
7899 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007900 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007901 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, dumpClient);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007902 if (needSep) {
7903 pw.println(" ");
7904 }
7905 if (dumpAll) {
7906 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007907 }
7908 dumpProcessesLocked(fd, pw, args, opti, dumpAll);
7909 }
7910 }
7911
7912 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007913 int opti, boolean dumpAll, boolean dumpClient) {
7914 pw.println("ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)");
7915 pw.println(" Main stack:");
7916 dumpHistoryList(fd, pw, mMainStack.mHistory, " ", "Hist", true, !dumpAll, dumpClient);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007917 pw.println(" ");
7918 pw.println(" Running activities (most recent first):");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007919 dumpHistoryList(fd, pw, mMainStack.mLRUActivities, " ", "Run", false, !dumpAll, false);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007920 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007921 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007922 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007923 dumpHistoryList(fd, pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false,
7924 !dumpAll, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007925 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007926 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007927 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007928 pw.println(" Activities waiting to stop:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007929 dumpHistoryList(fd, pw, mMainStack.mStoppingActivities, " ", "Stop", false,
7930 !dumpAll, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007931 }
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08007932 if (mMainStack.mGoingToSleepActivities.size() > 0) {
7933 pw.println(" ");
7934 pw.println(" Activities waiting to sleep:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007935 dumpHistoryList(fd, pw, mMainStack.mGoingToSleepActivities, " ", "Sleep", false,
7936 !dumpAll, false);
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08007937 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007938 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007939 pw.println(" ");
7940 pw.println(" Activities waiting to finish:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007941 dumpHistoryList(fd, pw, mMainStack.mFinishingActivities, " ", "Fin", false,
7942 !dumpAll, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007943 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007944
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007945 pw.println(" ");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007946 if (mMainStack.mPausingActivity != null) {
7947 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
7948 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007949 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007950 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007951 if (dumpAll) {
7952 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
7953 pw.println(" mSleepTimeout: " + mMainStack.mSleepTimeout);
Dianne Hackborn90c52de2011-09-23 12:57:44 -07007954 pw.println(" mDismissKeyguardOnNextActivity: "
7955 + mMainStack.mDismissKeyguardOnNextActivity);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007956 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007957
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007958 if (mRecentTasks.size() > 0) {
7959 pw.println();
7960 pw.println(" Recent tasks:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007961
7962 final int N = mRecentTasks.size();
7963 for (int i=0; i<N; i++) {
7964 TaskRecord tr = mRecentTasks.get(i);
7965 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
7966 pw.println(tr);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007967 if (dumpAll) {
7968 mRecentTasks.get(i).dump(pw, " ");
7969 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007970 }
7971 }
7972
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007973 if (dumpAll) {
7974 pw.println(" ");
7975 pw.println(" mCurTask: " + mCurTask);
7976 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007977
7978 return true;
7979 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07007980
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007981 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
7982 int opti, boolean dumpAll) {
7983 boolean needSep = false;
7984 int numPers = 0;
7985
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007986 pw.println("ACTIVITY MANAGER RUNNING PROCESSES (dumpsys activity processes)");
7987
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007988 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007989 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
7990 final int NA = procs.size();
7991 for (int ia=0; ia<NA; ia++) {
7992 if (!needSep) {
7993 pw.println(" All known processes:");
7994 needSep = true;
7995 }
7996 ProcessRecord r = procs.valueAt(ia);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007997 pw.print(r.persistent ? " *PERS*" : " *APP*");
7998 pw.print(" UID "); pw.print(procs.keyAt(ia));
7999 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008000 r.dump(pw, " ");
8001 if (r.persistent) {
8002 numPers++;
8003 }
8004 }
8005 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008006 }
8007
8008 if (mLruProcesses.size() > 0) {
8009 if (needSep) pw.println(" ");
8010 needSep = true;
Dianne Hackborn905577f2011-09-07 18:31:28 -07008011 pw.println(" Process LRU list (sorted by oom_adj):");
Dianne Hackborn287952c2010-09-22 22:34:31 -07008012 dumpProcessOomList(pw, this, mLruProcesses, " ",
8013 "Proc", "PERS", false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008014 needSep = true;
8015 }
8016
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008017 if (dumpAll) {
8018 synchronized (mPidsSelfLocked) {
8019 if (mPidsSelfLocked.size() > 0) {
8020 if (needSep) pw.println(" ");
8021 needSep = true;
8022 pw.println(" PID mappings:");
8023 for (int i=0; i<mPidsSelfLocked.size(); i++) {
8024 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
8025 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
8026 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008027 }
8028 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008029 }
8030
8031 if (mForegroundProcesses.size() > 0) {
8032 if (needSep) pw.println(" ");
8033 needSep = true;
8034 pw.println(" Foreground Processes:");
8035 for (int i=0; i<mForegroundProcesses.size(); i++) {
8036 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
8037 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008038 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008039 }
8040
8041 if (mPersistentStartingProcesses.size() > 0) {
8042 if (needSep) pw.println(" ");
8043 needSep = true;
8044 pw.println(" Persisent processes that are starting:");
8045 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07008046 "Starting Norm", "Restarting PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008047 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008048
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008049 if (mRemovedProcesses.size() > 0) {
8050 if (needSep) pw.println(" ");
8051 needSep = true;
8052 pw.println(" Processes that are being removed:");
8053 dumpProcessList(pw, this, mRemovedProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07008054 "Removed Norm", "Removed PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008055 }
8056
8057 if (mProcessesOnHold.size() > 0) {
8058 if (needSep) pw.println(" ");
8059 needSep = true;
8060 pw.println(" Processes that are on old until the system is ready:");
8061 dumpProcessList(pw, this, mProcessesOnHold, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07008062 "OnHold Norm", "OnHold PERS");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008063 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008064
Dianne Hackborn287952c2010-09-22 22:34:31 -07008065 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008066
8067 if (mProcessCrashTimes.getMap().size() > 0) {
8068 if (needSep) pw.println(" ");
8069 needSep = true;
8070 pw.println(" Time since processes crashed:");
8071 long now = SystemClock.uptimeMillis();
8072 for (Map.Entry<String, SparseArray<Long>> procs
8073 : mProcessCrashTimes.getMap().entrySet()) {
8074 SparseArray<Long> uids = procs.getValue();
8075 final int N = uids.size();
8076 for (int i=0; i<N; i++) {
8077 pw.print(" Process "); pw.print(procs.getKey());
8078 pw.print(" uid "); pw.print(uids.keyAt(i));
8079 pw.print(": last crashed ");
8080 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008081 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008082 }
8083 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008084 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008085
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008086 if (mBadProcesses.getMap().size() > 0) {
8087 if (needSep) pw.println(" ");
8088 needSep = true;
8089 pw.println(" Bad processes:");
8090 for (Map.Entry<String, SparseArray<Long>> procs
8091 : mBadProcesses.getMap().entrySet()) {
8092 SparseArray<Long> uids = procs.getValue();
8093 final int N = uids.size();
8094 for (int i=0; i<N; i++) {
8095 pw.print(" Bad process "); pw.print(procs.getKey());
8096 pw.print(" uid "); pw.print(uids.keyAt(i));
8097 pw.print(": crashed at time ");
8098 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008099 }
8100 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008101 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008102
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008103 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008104 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackborn860755f2010-06-03 18:47:52 -07008105 if (mHeavyWeightProcess != null) {
8106 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
8107 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008108 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008109 if (dumpAll) {
8110 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackborn3d0724d2011-05-12 15:39:41 -07008111 if (mCompatModePackages.getPackages().size() > 0) {
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07008112 pw.println(" mScreenCompatPackages:");
8113 for (Map.Entry<String, Integer> entry
8114 : mCompatModePackages.getPackages().entrySet()) {
8115 String pkg = entry.getKey();
8116 int mode = entry.getValue();
8117 pw.print(" "); pw.print(pkg); pw.print(": ");
8118 pw.print(mode); pw.println();
8119 }
Dianne Hackbornaa9d84c2011-05-09 19:00:59 -07008120 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008121 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008122 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
8123 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
8124 || mOrigWaitForDebugger) {
8125 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
8126 + " mDebugTransient=" + mDebugTransient
8127 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
8128 }
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07008129 if (mProfileApp != null || mProfileProc != null || mProfileFile != null
8130 || mProfileFd != null) {
8131 pw.println(" mProfileApp=" + mProfileApp + " mProfileProc=" + mProfileProc);
8132 pw.println(" mProfileFile=" + mProfileFile + " mProfileFd=" + mProfileFd);
8133 pw.println(" mProfileType=" + mProfileType + " mAutoStopProfiler="
8134 + mAutoStopProfiler);
8135 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008136 if (mAlwaysFinishActivities || mController != null) {
8137 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
8138 + " mController=" + mController);
8139 }
8140 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008141 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008142 pw.println(" mStartRunning=" + mStartRunning
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07008143 + " mProcessesReady=" + mProcessesReady
8144 + " mSystemReady=" + mSystemReady);
8145 pw.println(" mBooting=" + mBooting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008146 + " mBooted=" + mBooted
8147 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008148 pw.print(" mLastPowerCheckRealtime=");
8149 TimeUtils.formatDuration(mLastPowerCheckRealtime, pw);
8150 pw.println("");
8151 pw.print(" mLastPowerCheckUptime=");
8152 TimeUtils.formatDuration(mLastPowerCheckUptime, pw);
8153 pw.println("");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008154 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
8155 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07008156 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008157 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008158
8159 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008160 }
8161
Dianne Hackborn287952c2010-09-22 22:34:31 -07008162 boolean dumpProcessesToGc(FileDescriptor fd, PrintWriter pw, String[] args,
8163 int opti, boolean needSep, boolean dumpAll) {
8164 if (mProcessesToGc.size() > 0) {
8165 if (needSep) pw.println(" ");
8166 needSep = true;
8167 pw.println(" Processes that are waiting to GC:");
8168 long now = SystemClock.uptimeMillis();
8169 for (int i=0; i<mProcessesToGc.size(); i++) {
8170 ProcessRecord proc = mProcessesToGc.get(i);
8171 pw.print(" Process "); pw.println(proc);
8172 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
8173 pw.print(", last gced=");
8174 pw.print(now-proc.lastRequestedGc);
8175 pw.print(" ms ago, last lowMem=");
8176 pw.print(now-proc.lastLowMemory);
8177 pw.println(" ms ago");
8178
8179 }
8180 }
8181 return needSep;
8182 }
8183
8184 boolean dumpOomLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8185 int opti, boolean dumpAll) {
8186 boolean needSep = false;
8187
8188 if (mLruProcesses.size() > 0) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07008189 if (needSep) pw.println(" ");
8190 needSep = true;
Dianne Hackbornc68c9132011-07-29 01:25:18 -07008191 pw.println(" OOM levels:");
Dianne Hackborn7d608422011-08-07 16:24:18 -07008192 pw.print(" SYSTEM_ADJ: "); pw.println(ProcessList.SYSTEM_ADJ);
8193 pw.print(" CORE_SERVER_ADJ: "); pw.println(ProcessList.CORE_SERVER_ADJ);
8194 pw.print(" FOREGROUND_APP_ADJ: "); pw.println(ProcessList.FOREGROUND_APP_ADJ);
8195 pw.print(" VISIBLE_APP_ADJ: "); pw.println(ProcessList.VISIBLE_APP_ADJ);
8196 pw.print(" PERCEPTIBLE_APP_ADJ: "); pw.println(ProcessList.PERCEPTIBLE_APP_ADJ);
8197 pw.print(" HEAVY_WEIGHT_APP_ADJ: "); pw.println(ProcessList.HEAVY_WEIGHT_APP_ADJ);
8198 pw.print(" BACKUP_APP_ADJ: "); pw.println(ProcessList.BACKUP_APP_ADJ);
8199 pw.print(" SECONDARY_SERVER_ADJ: "); pw.println(ProcessList.SECONDARY_SERVER_ADJ);
8200 pw.print(" HOME_APP_ADJ: "); pw.println(ProcessList.HOME_APP_ADJ);
8201 pw.print(" HIDDEN_APP_MIN_ADJ: "); pw.println(ProcessList.HIDDEN_APP_MIN_ADJ);
8202 pw.print(" EMPTY_APP_ADJ: "); pw.println(ProcessList.EMPTY_APP_ADJ);
Dianne Hackbornc68c9132011-07-29 01:25:18 -07008203
8204 if (needSep) pw.println(" ");
8205 needSep = true;
Dianne Hackborn287952c2010-09-22 22:34:31 -07008206 pw.println(" Process OOM control:");
Dianne Hackborn905577f2011-09-07 18:31:28 -07008207 dumpProcessOomList(pw, this, mLruProcesses, " ",
Dianne Hackborn287952c2010-09-22 22:34:31 -07008208 "Proc", "PERS", true);
8209 needSep = true;
8210 }
8211
8212 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
8213
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008214 pw.println();
Dianne Hackborn287952c2010-09-22 22:34:31 -07008215 pw.println(" mHomeProcess: " + mHomeProcess);
8216 if (mHeavyWeightProcess != null) {
8217 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
8218 }
8219
8220 return true;
8221 }
8222
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008223 /**
8224 * There are three ways to call this:
8225 * - no service specified: dump all the services
8226 * - a flattened component name that matched an existing service was specified as the
8227 * first arg: dump that one service
8228 * - the first arg isn't the flattened component name of an existing service:
8229 * dump all services whose component contains the first arg as a substring
8230 */
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008231 protected boolean dumpService(FileDescriptor fd, PrintWriter pw, String name, String[] args,
8232 int opti, boolean dumpAll) {
8233 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008234
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008235 if ("all".equals(name)) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07008236 synchronized (this) {
8237 for (ServiceRecord r1 : mServices.values()) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008238 services.add(r1);
8239 }
8240 }
8241 } else {
8242 ComponentName componentName = name != null
8243 ? ComponentName.unflattenFromString(name) : null;
8244 int objectId = 0;
8245 if (componentName == null) {
8246 // Not a '/' separated full component name; maybe an object ID?
8247 try {
8248 objectId = Integer.parseInt(name, 16);
8249 name = null;
8250 componentName = null;
8251 } catch (RuntimeException e) {
8252 }
8253 }
8254
8255 synchronized (this) {
8256 for (ServiceRecord r1 : mServices.values()) {
8257 if (componentName != null) {
8258 if (r1.name.equals(componentName)) {
8259 services.add(r1);
8260 }
8261 } else if (name != null) {
8262 if (r1.name.flattenToString().contains(name)) {
8263 services.add(r1);
8264 }
8265 } else if (System.identityHashCode(r1) == objectId) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07008266 services.add(r1);
8267 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008268 }
8269 }
8270 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008271
8272 if (services.size() <= 0) {
8273 return false;
8274 }
8275
8276 boolean needSep = false;
8277 for (int i=0; i<services.size(); i++) {
8278 if (needSep) {
8279 pw.println();
8280 }
8281 needSep = true;
8282 dumpService("", fd, pw, services.get(i), args, dumpAll);
8283 }
8284 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008285 }
8286
8287 /**
8288 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
8289 * there is a thread associated with the service.
8290 */
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008291 private void dumpService(String prefix, FileDescriptor fd, PrintWriter pw,
8292 final ServiceRecord r, String[] args, boolean dumpAll) {
8293 String innerPrefix = prefix + " ";
8294 synchronized (this) {
8295 pw.print(prefix); pw.print("SERVICE ");
8296 pw.print(r.shortName); pw.print(" ");
8297 pw.print(Integer.toHexString(System.identityHashCode(r)));
8298 pw.print(" pid=");
8299 if (r.app != null) pw.println(r.app.pid);
8300 else pw.println("(not running)");
8301 if (dumpAll) {
8302 r.dump(pw, innerPrefix);
8303 }
8304 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008305 if (r.app != null && r.app.thread != null) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008306 pw.print(prefix); pw.println(" Client:");
8307 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008308 try {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008309 TransferPipe tp = new TransferPipe();
8310 try {
8311 r.app.thread.dumpService(tp.getWriteFd().getFileDescriptor(), r, args);
8312 tp.setBufferPrefix(prefix + " ");
8313 tp.go(fd);
8314 } finally {
8315 tp.kill();
8316 }
8317 } catch (IOException e) {
8318 pw.println(prefix + " Failure while dumping the service: " + e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008319 } catch (RemoteException e) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008320 pw.println(prefix + " Got a RemoteException while dumping the service");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008321 }
8322 }
8323 }
8324
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07008325 static class ItemMatcher {
8326 ArrayList<ComponentName> components;
8327 ArrayList<String> strings;
8328 ArrayList<Integer> objects;
8329 boolean all;
8330
8331 ItemMatcher() {
8332 all = true;
8333 }
8334
8335 void build(String name) {
8336 ComponentName componentName = ComponentName.unflattenFromString(name);
8337 if (componentName != null) {
8338 if (components == null) {
8339 components = new ArrayList<ComponentName>();
8340 }
8341 components.add(componentName);
8342 all = false;
8343 } else {
8344 int objectId = 0;
8345 // Not a '/' separated full component name; maybe an object ID?
8346 try {
8347 objectId = Integer.parseInt(name, 16);
8348 if (objects == null) {
8349 objects = new ArrayList<Integer>();
8350 }
8351 objects.add(objectId);
8352 all = false;
8353 } catch (RuntimeException e) {
8354 // Not an integer; just do string match.
8355 if (strings == null) {
8356 strings = new ArrayList<String>();
8357 }
8358 strings.add(name);
8359 all = false;
8360 }
8361 }
8362 }
8363
8364 int build(String[] args, int opti) {
8365 for (; opti<args.length; opti++) {
8366 String name = args[opti];
8367 if ("--".equals(name)) {
8368 return opti+1;
8369 }
8370 build(name);
8371 }
8372 return opti;
8373 }
8374
8375 boolean match(Object object, ComponentName comp) {
8376 if (all) {
8377 return true;
8378 }
8379 if (components != null) {
8380 for (int i=0; i<components.size(); i++) {
8381 if (components.get(i).equals(comp)) {
8382 return true;
8383 }
8384 }
8385 }
8386 if (objects != null) {
8387 for (int i=0; i<objects.size(); i++) {
8388 if (System.identityHashCode(object) == objects.get(i)) {
8389 return true;
8390 }
8391 }
8392 }
8393 if (strings != null) {
8394 String flat = comp.flattenToString();
8395 for (int i=0; i<strings.size(); i++) {
8396 if (flat.contains(strings.get(i))) {
8397 return true;
8398 }
8399 }
8400 }
8401 return false;
8402 }
8403 }
8404
Dianne Hackborn625ac272010-09-17 18:29:22 -07008405 /**
8406 * There are three things that cmd can be:
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07008407 * - a flattened component name that matches an existing activity
Dianne Hackborn625ac272010-09-17 18:29:22 -07008408 * - the cmd arg isn't the flattened component name of an existing activity:
8409 * dump all activity whose component contains the cmd as a substring
8410 * - A hex number of the ActivityRecord object instance.
8411 */
8412 protected boolean dumpActivity(FileDescriptor fd, PrintWriter pw, String name, String[] args,
8413 int opti, boolean dumpAll) {
Dianne Hackborn625ac272010-09-17 18:29:22 -07008414 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008415
8416 if ("all".equals(name)) {
8417 synchronized (this) {
8418 for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
Dianne Hackborn625ac272010-09-17 18:29:22 -07008419 activities.add(r1);
8420 }
8421 }
Dianne Hackbornf9302322011-06-14 18:36:14 -07008422 } else if ("top".equals(name)) {
8423 synchronized (this) {
8424 final int N = mMainStack.mHistory.size();
8425 if (N > 0) {
8426 activities.add((ActivityRecord)mMainStack.mHistory.get(N-1));
8427 }
8428 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008429 } else {
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07008430 ItemMatcher matcher = new ItemMatcher();
8431 matcher.build(name);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008432
8433 synchronized (this) {
8434 for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07008435 if (matcher.match(r1, r1.intent.getComponent())) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008436 activities.add(r1);
8437 }
8438 }
8439 }
Dianne Hackborn625ac272010-09-17 18:29:22 -07008440 }
8441
8442 if (activities.size() <= 0) {
8443 return false;
8444 }
8445
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008446 String[] newArgs = new String[args.length - opti];
8447 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
8448
Dianne Hackborn30d71892010-12-11 10:37:55 -08008449 TaskRecord lastTask = null;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008450 boolean needSep = false;
Dianne Hackborn30d71892010-12-11 10:37:55 -08008451 for (int i=activities.size()-1; i>=0; i--) {
8452 ActivityRecord r = (ActivityRecord)activities.get(i);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008453 if (needSep) {
8454 pw.println();
8455 }
8456 needSep = true;
8457 synchronized (this) {
8458 if (lastTask != r.task) {
8459 lastTask = r.task;
8460 pw.print("TASK "); pw.print(lastTask.affinity);
8461 pw.print(" id="); pw.println(lastTask.taskId);
8462 if (dumpAll) {
8463 lastTask.dump(pw, " ");
8464 }
Dianne Hackborn30d71892010-12-11 10:37:55 -08008465 }
8466 }
8467 dumpActivity(" ", fd, pw, activities.get(i), newArgs, dumpAll);
Dianne Hackborn625ac272010-09-17 18:29:22 -07008468 }
8469 return true;
8470 }
8471
8472 /**
8473 * Invokes IApplicationThread.dumpActivity() on the thread of the specified activity if
8474 * there is a thread associated with the activity.
8475 */
Dianne Hackborn30d71892010-12-11 10:37:55 -08008476 private void dumpActivity(String prefix, FileDescriptor fd, PrintWriter pw,
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008477 final ActivityRecord r, String[] args, boolean dumpAll) {
8478 String innerPrefix = prefix + " ";
Dianne Hackborn30d71892010-12-11 10:37:55 -08008479 synchronized (this) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008480 pw.print(prefix); pw.print("ACTIVITY "); pw.print(r.shortComponentName);
8481 pw.print(" "); pw.print(Integer.toHexString(System.identityHashCode(r)));
8482 pw.print(" pid=");
Dianne Hackborn30d71892010-12-11 10:37:55 -08008483 if (r.app != null) pw.println(r.app.pid);
8484 else pw.println("(not running)");
8485 if (dumpAll) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008486 r.dump(pw, innerPrefix);
Dianne Hackborn625ac272010-09-17 18:29:22 -07008487 }
Dianne Hackborn625ac272010-09-17 18:29:22 -07008488 }
8489 if (r.app != null && r.app.thread != null) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008490 // flush anything that is already in the PrintWriter since the thread is going
8491 // to write to the file descriptor directly
8492 pw.flush();
Dianne Hackborn625ac272010-09-17 18:29:22 -07008493 try {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008494 TransferPipe tp = new TransferPipe();
8495 try {
8496 r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(), r,
8497 innerPrefix, args);
8498 tp.go(fd);
8499 } finally {
8500 tp.kill();
8501 }
8502 } catch (IOException e) {
8503 pw.println(innerPrefix + "Failure while dumping the activity: " + e);
Dianne Hackborn625ac272010-09-17 18:29:22 -07008504 } catch (RemoteException e) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008505 pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
Dianne Hackborn625ac272010-09-17 18:29:22 -07008506 }
8507 }
8508 }
8509
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008510 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8511 int opti, boolean dumpAll) {
8512 boolean needSep = false;
8513
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008514 pw.println("ACTIVITY MANAGER BROADCAST STATE (dumpsys activity broadcasts)");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008515 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008516 if (mRegisteredReceivers.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008517 pw.println(" Registered Receivers:");
8518 Iterator it = mRegisteredReceivers.values().iterator();
8519 while (it.hasNext()) {
8520 ReceiverList r = (ReceiverList)it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008521 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008522 r.dump(pw, " ");
8523 }
8524 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008525
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008526 pw.println();
8527 pw.println(" Receiver Resolver Table:");
8528 mReceiverResolver.dump(pw, null, " ", null, false);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008529 needSep = true;
8530 }
8531
8532 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
8533 || mPendingBroadcast != null) {
8534 if (mParallelBroadcasts.size() > 0) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008535 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008536 pw.println(" Active broadcasts:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008537 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008538 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
8539 pw.println(" Broadcast #" + i + ":");
8540 mParallelBroadcasts.get(i).dump(pw, " ");
8541 }
8542 if (mOrderedBroadcasts.size() > 0) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008543 pw.println();
Dianne Hackborn399cccb2010-04-13 22:57:49 -07008544 pw.println(" Active ordered broadcasts:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008545 }
8546 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
8547 pw.println(" Serialized Broadcast #" + i + ":");
8548 mOrderedBroadcasts.get(i).dump(pw, " ");
8549 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008550 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008551 pw.println(" Pending broadcast:");
8552 if (mPendingBroadcast != null) {
8553 mPendingBroadcast.dump(pw, " ");
8554 } else {
8555 pw.println(" (null)");
8556 }
8557 needSep = true;
8558 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008559
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008560 if (needSep) {
8561 pw.println();
8562 }
8563 pw.println(" Historical broadcasts:");
8564 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
8565 BroadcastRecord r = mBroadcastHistory[i];
8566 if (r == null) {
8567 break;
8568 }
8569 if (dumpAll) {
8570 pw.print(" Historical Broadcast #"); pw.print(i); pw.println(":");
8571 r.dump(pw, " ");
8572 } else {
8573 if (i >= 50) {
8574 pw.println(" ...");
Dianne Hackborn12527f92009-11-11 17:39:50 -08008575 break;
8576 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008577 pw.print(" #"); pw.print(i); pw.print(": "); pw.println(r);
Dianne Hackborn12527f92009-11-11 17:39:50 -08008578 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008579 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008580 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008581
8582 if (mStickyBroadcasts != null) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008583 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008584 pw.println(" Sticky broadcasts:");
8585 StringBuilder sb = new StringBuilder(128);
8586 for (Map.Entry<String, ArrayList<Intent>> ent
8587 : mStickyBroadcasts.entrySet()) {
8588 pw.print(" * Sticky action "); pw.print(ent.getKey());
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008589 if (dumpAll) {
8590 pw.println(":");
8591 ArrayList<Intent> intents = ent.getValue();
8592 final int N = intents.size();
8593 for (int i=0; i<N; i++) {
8594 sb.setLength(0);
8595 sb.append(" Intent: ");
Dianne Hackborn90c52de2011-09-23 12:57:44 -07008596 intents.get(i).toShortString(sb, false, true, false);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008597 pw.println(sb.toString());
8598 Bundle bundle = intents.get(i).getExtras();
8599 if (bundle != null) {
8600 pw.print(" ");
8601 pw.println(bundle.toString());
8602 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008603 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008604 } else {
8605 pw.println("");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008606 }
8607 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008608 needSep = true;
8609 }
8610
8611 if (dumpAll) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008612 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008613 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008614 pw.println(" mHandler:");
8615 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008616 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008617 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008618
8619 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008620 }
8621
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008622 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008623 int opti, boolean dumpAll, boolean dumpClient) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008624 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008625
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07008626 ItemMatcher matcher = new ItemMatcher();
8627 matcher.build(args, opti);
8628
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008629 pw.println("ACTIVITY MANAGER SERVICES (dumpsys activity services)");
8630 if (mServices.size() > 0) {
8631 pw.println(" Active services:");
8632 long nowReal = SystemClock.elapsedRealtime();
8633 Iterator<ServiceRecord> it = mServices.values().iterator();
8634 needSep = false;
8635 while (it.hasNext()) {
8636 ServiceRecord r = it.next();
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07008637 if (!matcher.match(r, r.name)) {
8638 continue;
8639 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008640 if (needSep) {
8641 pw.println();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008642 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008643 pw.print(" * "); pw.println(r);
8644 if (dumpAll) {
8645 r.dump(pw, " ");
8646 needSep = true;
8647 } else {
8648 pw.print(" app="); pw.println(r.app);
8649 pw.print(" created=");
8650 TimeUtils.formatDuration(r.createTime, nowReal, pw);
8651 pw.print(" started="); pw.print(r.startRequested);
8652 pw.print(" connections="); pw.println(r.connections.size());
8653 }
8654 if (dumpClient && r.app != null && r.app.thread != null) {
8655 pw.println(" Client:");
8656 pw.flush();
8657 try {
8658 TransferPipe tp = new TransferPipe();
8659 try {
8660 r.app.thread.dumpService(
8661 tp.getWriteFd().getFileDescriptor(), r, args);
8662 tp.setBufferPrefix(" ");
8663 // Short timeout, since blocking here can
8664 // deadlock with the application.
8665 tp.go(fd, 2000);
8666 } finally {
8667 tp.kill();
8668 }
8669 } catch (IOException e) {
8670 pw.println(" Failure while dumping the service: " + e);
8671 } catch (RemoteException e) {
8672 pw.println(" Got a RemoteException while dumping the service");
8673 }
8674 needSep = true;
8675 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008676 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008677 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008678 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008679
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008680 if (mPendingServices.size() > 0) {
8681 if (needSep) pw.println(" ");
8682 pw.println(" Pending services:");
8683 for (int i=0; i<mPendingServices.size(); i++) {
8684 ServiceRecord r = mPendingServices.get(i);
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07008685 if (!matcher.match(r, r.name)) {
8686 continue;
8687 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008688 pw.print(" * Pending "); pw.println(r);
8689 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008690 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008691 needSep = true;
8692 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008693
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008694 if (mRestartingServices.size() > 0) {
8695 if (needSep) pw.println(" ");
8696 pw.println(" Restarting services:");
8697 for (int i=0; i<mRestartingServices.size(); i++) {
8698 ServiceRecord r = mRestartingServices.get(i);
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07008699 if (!matcher.match(r, r.name)) {
8700 continue;
8701 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008702 pw.print(" * Restarting "); pw.println(r);
8703 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008704 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008705 needSep = true;
8706 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008707
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008708 if (mStoppingServices.size() > 0) {
8709 if (needSep) pw.println(" ");
8710 pw.println(" Stopping services:");
8711 for (int i=0; i<mStoppingServices.size(); i++) {
8712 ServiceRecord r = mStoppingServices.get(i);
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07008713 if (!matcher.match(r, r.name)) {
8714 continue;
8715 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008716 pw.print(" * Stopping "); pw.println(r);
8717 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008718 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008719 needSep = true;
8720 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008721
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008722 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008723 if (mServiceConnections.size() > 0) {
8724 if (needSep) pw.println(" ");
8725 pw.println(" Connection bindings to services:");
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008726 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008727 = mServiceConnections.values().iterator();
8728 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008729 ArrayList<ConnectionRecord> r = it.next();
8730 for (int i=0; i<r.size(); i++) {
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07008731 ConnectionRecord cr = r.get(i);
8732 if (!matcher.match(cr.binding.service, cr.binding.service.name)) {
8733 continue;
8734 }
8735 pw.print(" * "); pw.println(cr);
8736 cr.dump(pw, " ");
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07008737 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008738 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008739 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008740 }
8741 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008742
8743 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008744 }
8745
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008746 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8747 int opti, boolean dumpAll) {
8748 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008749
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07008750 ItemMatcher matcher = new ItemMatcher();
8751 matcher.build(args, opti);
8752
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008753 pw.println("ACTIVITY MANAGER CONTENT PROVIDERS (dumpsys activity providers)");
8754 if (mProvidersByClass.size() > 0) {
8755 if (needSep) pw.println(" ");
8756 pw.println(" Published content providers (by class):");
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07008757 Iterator<Map.Entry<ComponentName, ContentProviderRecord>> it
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008758 = mProvidersByClass.entrySet().iterator();
8759 while (it.hasNext()) {
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07008760 Map.Entry<ComponentName, ContentProviderRecord> e = it.next();
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008761 ContentProviderRecord r = e.getValue();
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07008762 ComponentName comp = e.getKey();
8763 String cls = comp.getClassName();
8764 int end = cls.lastIndexOf('.');
8765 if (end > 0 && end < (cls.length()-2)) {
8766 cls = cls.substring(end+1);
8767 }
8768 if (!matcher.match(r, comp)) {
8769 continue;
8770 }
8771 pw.print(" * "); pw.print(cls); pw.print(" (");
8772 pw.print(comp.flattenToShortString()); pw.print(")");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008773 if (dumpAll) {
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07008774 pw.println();
8775 r.dump(pw, " ");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008776 } else {
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07008777 pw.print(" * "); pw.print(e.getKey().flattenToShortString());
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07008778 if (r.proc != null) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008779 pw.println(":");
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07008780 pw.print(" "); pw.println(r.proc);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008781 } else {
8782 pw.println();
8783 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008784 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008785 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008786 needSep = true;
8787 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008788
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008789 if (dumpAll) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008790 if (mProvidersByName.size() > 0) {
8791 pw.println(" ");
8792 pw.println(" Authority to provider mappings:");
Dianne Hackborn860755f2010-06-03 18:47:52 -07008793 Iterator<Map.Entry<String, ContentProviderRecord>> it
8794 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008795 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07008796 Map.Entry<String, ContentProviderRecord> e = it.next();
8797 ContentProviderRecord r = e.getValue();
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07008798 if (!matcher.match(r, r.name)) {
8799 continue;
8800 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008801 pw.print(" "); pw.print(e.getKey()); pw.print(": ");
8802 pw.println(r);
8803 }
8804 needSep = true;
8805 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008806 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008807
8808 if (mLaunchingProviders.size() > 0) {
8809 if (needSep) pw.println(" ");
8810 pw.println(" Launching content providers:");
8811 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
8812 pw.print(" Launching #"); pw.print(i); pw.print(": ");
8813 pw.println(mLaunchingProviders.get(i));
8814 }
8815 needSep = true;
8816 }
8817
8818 if (mGrantedUriPermissions.size() > 0) {
8819 pw.println();
8820 pw.println("Granted Uri Permissions:");
8821 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
8822 int uid = mGrantedUriPermissions.keyAt(i);
8823 HashMap<Uri, UriPermission> perms
8824 = mGrantedUriPermissions.valueAt(i);
8825 pw.print(" * UID "); pw.print(uid);
8826 pw.println(" holds:");
8827 for (UriPermission perm : perms.values()) {
8828 pw.print(" "); pw.println(perm);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008829 if (dumpAll) {
8830 perm.dump(pw, " ");
8831 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008832 }
8833 }
8834 needSep = true;
8835 }
8836
8837 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008838 }
8839
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008840 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8841 int opti, boolean dumpAll) {
8842 boolean needSep = false;
8843
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008844 if (this.mIntentSenderRecords.size() > 0) {
8845 pw.println("ACTIVITY MANAGER PENDING INTENTS (dumpsys activity intents)");
8846 Iterator<WeakReference<PendingIntentRecord>> it
8847 = mIntentSenderRecords.values().iterator();
8848 while (it.hasNext()) {
8849 WeakReference<PendingIntentRecord> ref = it.next();
8850 PendingIntentRecord rec = ref != null ? ref.get(): null;
8851 needSep = true;
8852 if (rec != null) {
8853 pw.print(" * "); pw.println(rec);
8854 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008855 rec.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008856 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008857 } else {
8858 pw.print(" * "); pw.println(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008859 }
8860 }
8861 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008862
8863 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008864 }
8865
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008866 private static final void dumpHistoryList(FileDescriptor fd, PrintWriter pw, List list,
8867 String prefix, String label, boolean complete, boolean brief, boolean client) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008868 TaskRecord lastTask = null;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008869 boolean needNL = false;
8870 final String innerPrefix = prefix + " ";
8871 final String[] args = new String[0];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008872 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008873 final ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackbornf26fd992011-04-08 18:14:09 -07008874 final boolean full = !brief && (complete || !r.isInHistory());
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008875 if (needNL) {
8876 pw.println(" ");
8877 needNL = false;
8878 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008879 if (lastTask != r.task) {
8880 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008881 pw.print(prefix);
8882 pw.print(full ? "* " : " ");
8883 pw.println(lastTask);
8884 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008885 lastTask.dump(pw, prefix + " ");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008886 } else if (complete) {
8887 // Complete + brief == give a summary. Isn't that obvious?!?
8888 if (lastTask.intent != null) {
Dianne Hackborn90c52de2011-09-23 12:57:44 -07008889 pw.print(prefix); pw.print(" ");
8890 pw.println(lastTask.intent.toInsecureString());
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008891 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008892 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008893 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008894 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
8895 pw.print(" #"); pw.print(i); pw.print(": ");
8896 pw.println(r);
8897 if (full) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008898 r.dump(pw, innerPrefix);
8899 } else if (complete) {
8900 // Complete + brief == give a summary. Isn't that obvious?!?
Dianne Hackborn90c52de2011-09-23 12:57:44 -07008901 pw.print(innerPrefix); pw.println(r.intent.toInsecureString());
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008902 if (r.app != null) {
8903 pw.print(innerPrefix); pw.println(r.app);
8904 }
8905 }
8906 if (client && r.app != null && r.app.thread != null) {
8907 // flush anything that is already in the PrintWriter since the thread is going
8908 // to write to the file descriptor directly
8909 pw.flush();
8910 try {
8911 TransferPipe tp = new TransferPipe();
8912 try {
8913 r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(), r,
8914 innerPrefix, args);
8915 // Short timeout, since blocking here can
8916 // deadlock with the application.
8917 tp.go(fd, 2000);
8918 } finally {
8919 tp.kill();
8920 }
8921 } catch (IOException e) {
8922 pw.println(innerPrefix + "Failure while dumping the activity: " + e);
8923 } catch (RemoteException e) {
8924 pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
8925 }
8926 needNL = true;
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07008927 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008928 }
8929 }
8930
Dianne Hackborn09c916b2009-12-08 14:50:51 -08008931 private static String buildOomTag(String prefix, String space, int val, int base) {
8932 if (val == base) {
8933 if (space == null) return prefix;
8934 return prefix + " ";
8935 }
8936 return prefix + "+" + Integer.toString(val-base);
8937 }
8938
8939 private static final int dumpProcessList(PrintWriter pw,
8940 ActivityManagerService service, List list,
Dianne Hackborn287952c2010-09-22 22:34:31 -07008941 String prefix, String normalLabel, String persistentLabel) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008942 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07008943 final int N = list.size()-1;
8944 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008945 ProcessRecord r = (ProcessRecord)list.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008946 pw.println(String.format("%s%s #%2d: %s",
8947 prefix, (r.persistent ? persistentLabel : normalLabel),
8948 i, r.toString()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008949 if (r.persistent) {
8950 numPers++;
8951 }
8952 }
8953 return numPers;
8954 }
8955
Dianne Hackborn287952c2010-09-22 22:34:31 -07008956 private static final void dumpProcessOomList(PrintWriter pw,
Dianne Hackborn905577f2011-09-07 18:31:28 -07008957 ActivityManagerService service, List<ProcessRecord> origList,
Dianne Hackborn287952c2010-09-22 22:34:31 -07008958 String prefix, String normalLabel, String persistentLabel,
8959 boolean inclDetails) {
8960
Dianne Hackborn905577f2011-09-07 18:31:28 -07008961 ArrayList<Pair<ProcessRecord, Integer>> list
8962 = new ArrayList<Pair<ProcessRecord, Integer>>(origList.size());
8963 for (int i=0; i<origList.size(); i++) {
8964 list.add(new Pair<ProcessRecord, Integer>(origList.get(i), i));
8965 }
8966
8967 Comparator<Pair<ProcessRecord, Integer>> comparator
8968 = new Comparator<Pair<ProcessRecord, Integer>>() {
8969 @Override
8970 public int compare(Pair<ProcessRecord, Integer> object1,
8971 Pair<ProcessRecord, Integer> object2) {
8972 if (object1.first.setAdj != object2.first.setAdj) {
8973 return object1.first.setAdj > object2.first.setAdj ? -1 : 1;
8974 }
8975 if (object1.second.intValue() != object2.second.intValue()) {
8976 return object1.second.intValue() > object2.second.intValue() ? -1 : 1;
8977 }
8978 return 0;
8979 }
8980 };
8981
8982 Collections.sort(list, comparator);
8983
Dianne Hackborn287952c2010-09-22 22:34:31 -07008984 final long curRealtime = SystemClock.elapsedRealtime();
8985 final long realtimeSince = curRealtime - service.mLastPowerCheckRealtime;
8986 final long curUptime = SystemClock.uptimeMillis();
8987 final long uptimeSince = curUptime - service.mLastPowerCheckUptime;
8988
8989 final int N = list.size()-1;
8990 for (int i=N; i>=0; i--) {
Dianne Hackborn905577f2011-09-07 18:31:28 -07008991 ProcessRecord r = list.get(i).first;
Dianne Hackborn287952c2010-09-22 22:34:31 -07008992 String oomAdj;
Dianne Hackborn7d608422011-08-07 16:24:18 -07008993 if (r.setAdj >= ProcessList.EMPTY_APP_ADJ) {
8994 oomAdj = buildOomTag("empty", null, r.setAdj, ProcessList.EMPTY_APP_ADJ);
8995 } else if (r.setAdj >= ProcessList.HIDDEN_APP_MIN_ADJ) {
8996 oomAdj = buildOomTag("bak", " ", r.setAdj, ProcessList.HIDDEN_APP_MIN_ADJ);
8997 } else if (r.setAdj >= ProcessList.HOME_APP_ADJ) {
8998 oomAdj = buildOomTag("home ", null, r.setAdj, ProcessList.HOME_APP_ADJ);
8999 } else if (r.setAdj >= ProcessList.SECONDARY_SERVER_ADJ) {
9000 oomAdj = buildOomTag("svc", " ", r.setAdj, ProcessList.SECONDARY_SERVER_ADJ);
9001 } else if (r.setAdj >= ProcessList.BACKUP_APP_ADJ) {
9002 oomAdj = buildOomTag("bckup", null, r.setAdj, ProcessList.BACKUP_APP_ADJ);
9003 } else if (r.setAdj >= ProcessList.HEAVY_WEIGHT_APP_ADJ) {
9004 oomAdj = buildOomTag("hvy ", null, r.setAdj, ProcessList.HEAVY_WEIGHT_APP_ADJ);
9005 } else if (r.setAdj >= ProcessList.PERCEPTIBLE_APP_ADJ) {
9006 oomAdj = buildOomTag("prcp ", null, r.setAdj, ProcessList.PERCEPTIBLE_APP_ADJ);
9007 } else if (r.setAdj >= ProcessList.VISIBLE_APP_ADJ) {
9008 oomAdj = buildOomTag("vis ", null, r.setAdj, ProcessList.VISIBLE_APP_ADJ);
9009 } else if (r.setAdj >= ProcessList.FOREGROUND_APP_ADJ) {
9010 oomAdj = buildOomTag("fore ", null, r.setAdj, ProcessList.FOREGROUND_APP_ADJ);
9011 } else if (r.setAdj >= ProcessList.CORE_SERVER_ADJ) {
9012 oomAdj = buildOomTag("core ", null, r.setAdj, ProcessList.CORE_SERVER_ADJ);
9013 } else if (r.setAdj >= ProcessList.SYSTEM_ADJ) {
9014 oomAdj = buildOomTag("sys ", null, r.setAdj, ProcessList.SYSTEM_ADJ);
Dianne Hackborn287952c2010-09-22 22:34:31 -07009015 } else {
9016 oomAdj = Integer.toString(r.setAdj);
9017 }
9018 String schedGroup;
9019 switch (r.setSchedGroup) {
9020 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
9021 schedGroup = "B";
9022 break;
9023 case Process.THREAD_GROUP_DEFAULT:
9024 schedGroup = "F";
9025 break;
9026 default:
9027 schedGroup = Integer.toString(r.setSchedGroup);
9028 break;
9029 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07009030 String foreground;
9031 if (r.foregroundActivities) {
9032 foreground = "A";
9033 } else if (r.foregroundServices) {
9034 foreground = "S";
9035 } else {
9036 foreground = " ";
9037 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -07009038 pw.println(String.format("%s%s #%2d: adj=%s/%s%s trm=%2d %s (%s)",
Dianne Hackborn287952c2010-09-22 22:34:31 -07009039 prefix, (r.persistent ? persistentLabel : normalLabel),
Dianne Hackborn905577f2011-09-07 18:31:28 -07009040 N-list.get(i).second, oomAdj, schedGroup, foreground, r.trimMemoryLevel,
Dianne Hackbornce86ba82011-07-13 19:33:41 -07009041 r.toShortString(), r.adjType));
Dianne Hackborn287952c2010-09-22 22:34:31 -07009042 if (r.adjSource != null || r.adjTarget != null) {
9043 pw.print(prefix);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009044 pw.print(" ");
Dianne Hackborn287952c2010-09-22 22:34:31 -07009045 if (r.adjTarget instanceof ComponentName) {
9046 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
9047 } else if (r.adjTarget != null) {
9048 pw.print(r.adjTarget.toString());
9049 } else {
9050 pw.print("{null}");
9051 }
9052 pw.print("<=");
9053 if (r.adjSource instanceof ProcessRecord) {
9054 pw.print("Proc{");
9055 pw.print(((ProcessRecord)r.adjSource).toShortString());
9056 pw.println("}");
9057 } else if (r.adjSource != null) {
9058 pw.println(r.adjSource.toString());
9059 } else {
9060 pw.println("{null}");
9061 }
9062 }
9063 if (inclDetails) {
9064 pw.print(prefix);
9065 pw.print(" ");
9066 pw.print("oom: max="); pw.print(r.maxAdj);
9067 pw.print(" hidden="); pw.print(r.hiddenAdj);
9068 pw.print(" curRaw="); pw.print(r.curRawAdj);
9069 pw.print(" setRaw="); pw.print(r.setRawAdj);
9070 pw.print(" cur="); pw.print(r.curAdj);
9071 pw.print(" set="); pw.println(r.setAdj);
9072 pw.print(prefix);
9073 pw.print(" ");
9074 pw.print("keeping="); pw.print(r.keeping);
9075 pw.print(" hidden="); pw.print(r.hidden);
Dianne Hackbornc68c9132011-07-29 01:25:18 -07009076 pw.print(" empty="); pw.print(r.empty);
9077 pw.print(" hasAboveClient="); pw.println(r.hasAboveClient);
Dianne Hackborn287952c2010-09-22 22:34:31 -07009078
9079 if (!r.keeping) {
9080 if (r.lastWakeTime != 0) {
9081 long wtime;
9082 BatteryStatsImpl stats = service.mBatteryStatsService.getActiveStatistics();
9083 synchronized (stats) {
9084 wtime = stats.getProcessWakeTime(r.info.uid,
9085 r.pid, curRealtime);
9086 }
9087 long timeUsed = wtime - r.lastWakeTime;
9088 pw.print(prefix);
9089 pw.print(" ");
9090 pw.print("keep awake over ");
9091 TimeUtils.formatDuration(realtimeSince, pw);
9092 pw.print(" used ");
9093 TimeUtils.formatDuration(timeUsed, pw);
9094 pw.print(" (");
9095 pw.print((timeUsed*100)/realtimeSince);
9096 pw.println("%)");
9097 }
9098 if (r.lastCpuTime != 0) {
9099 long timeUsed = r.curCpuTime - r.lastCpuTime;
9100 pw.print(prefix);
9101 pw.print(" ");
9102 pw.print("run cpu over ");
9103 TimeUtils.formatDuration(uptimeSince, pw);
9104 pw.print(" used ");
9105 TimeUtils.formatDuration(timeUsed, pw);
9106 pw.print(" (");
9107 pw.print((timeUsed*100)/uptimeSince);
9108 pw.println("%)");
9109 }
9110 }
9111 }
9112 }
9113 }
9114
Dianne Hackbornb437e092011-08-05 17:50:29 -07009115 ArrayList<ProcessRecord> collectProcesses(PrintWriter pw, int start, String[] args) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009116 ArrayList<ProcessRecord> procs;
9117 synchronized (this) {
Dianne Hackbornb437e092011-08-05 17:50:29 -07009118 if (args != null && args.length > start
9119 && args[start].charAt(0) != '-') {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009120 procs = new ArrayList<ProcessRecord>();
9121 int pid = -1;
9122 try {
Dianne Hackbornb437e092011-08-05 17:50:29 -07009123 pid = Integer.parseInt(args[start]);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009124 } catch (NumberFormatException e) {
9125
9126 }
9127 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9128 ProcessRecord proc = mLruProcesses.get(i);
9129 if (proc.pid == pid) {
9130 procs.add(proc);
Dianne Hackbornb437e092011-08-05 17:50:29 -07009131 } else if (proc.processName.equals(args[start])) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009132 procs.add(proc);
9133 }
9134 }
9135 if (procs.size() <= 0) {
Dianne Hackbornb437e092011-08-05 17:50:29 -07009136 pw.println("No process found for: " + args[start]);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009137 return null;
9138 }
9139 } else {
9140 procs = new ArrayList<ProcessRecord>(mLruProcesses);
9141 }
9142 }
9143 return procs;
9144 }
9145
9146 final void dumpGraphicsHardwareUsage(FileDescriptor fd,
9147 PrintWriter pw, String[] args) {
Dianne Hackbornb437e092011-08-05 17:50:29 -07009148 ArrayList<ProcessRecord> procs = collectProcesses(pw, 0, args);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009149 if (procs == null) {
9150 return;
9151 }
9152
9153 long uptime = SystemClock.uptimeMillis();
9154 long realtime = SystemClock.elapsedRealtime();
9155 pw.println("Applications Graphics Acceleration Info:");
9156 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
9157
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009158 for (int i = procs.size() - 1 ; i >= 0 ; i--) {
9159 ProcessRecord r = procs.get(i);
Chet Haase9c1e23b2011-03-24 10:51:31 -07009160 if (r.thread != null) {
9161 pw.println("\n** Graphics info for pid " + r.pid + " [" + r.processName + "] **");
9162 pw.flush();
9163 try {
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009164 TransferPipe tp = new TransferPipe();
9165 try {
9166 r.thread.dumpGfxInfo(tp.getWriteFd().getFileDescriptor(), args);
9167 tp.go(fd);
9168 } finally {
9169 tp.kill();
9170 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009171 } catch (IOException e) {
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009172 pw.println("Failure while dumping the app: " + r);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009173 pw.flush();
Chet Haase9c1e23b2011-03-24 10:51:31 -07009174 } catch (RemoteException e) {
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009175 pw.println("Got a RemoteException while dumping the app " + r);
Chet Haase9c1e23b2011-03-24 10:51:31 -07009176 pw.flush();
9177 }
9178 }
9179 }
Chet Haase9c1e23b2011-03-24 10:51:31 -07009180 }
9181
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009182 final static class MemItem {
9183 final String label;
9184 final long pss;
Dianne Hackborna4bacb82011-08-24 15:12:38 -07009185 ArrayList<MemItem> subitems;
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009186
9187 public MemItem(String _label, long _pss) {
9188 label = _label;
9189 pss = _pss;
9190 }
9191 }
9192
Dianne Hackbornb437e092011-08-05 17:50:29 -07009193 final void dumpMemItems(PrintWriter pw, String prefix, ArrayList<MemItem> items,
9194 boolean sort) {
9195 if (sort) {
9196 Collections.sort(items, new Comparator<MemItem>() {
9197 @Override
9198 public int compare(MemItem lhs, MemItem rhs) {
9199 if (lhs.pss < rhs.pss) {
9200 return 1;
9201 } else if (lhs.pss > rhs.pss) {
9202 return -1;
9203 }
9204 return 0;
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009205 }
Dianne Hackbornb437e092011-08-05 17:50:29 -07009206 });
9207 }
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009208
9209 for (int i=0; i<items.size(); i++) {
9210 MemItem mi = items.get(i);
Dianne Hackborna4bacb82011-08-24 15:12:38 -07009211 pw.print(prefix); pw.printf("%7d Kb: ", mi.pss); pw.println(mi.label);
9212 if (mi.subitems != null) {
9213 dumpMemItems(pw, prefix + " ", mi.subitems, true);
9214 }
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009215 }
9216 }
9217
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009218 final void dumpApplicationMemoryUsage(FileDescriptor fd,
9219 PrintWriter pw, String prefix, String[] args) {
Dianne Hackbornb437e092011-08-05 17:50:29 -07009220 boolean dumpAll = false;
9221
9222 int opti = 0;
9223 while (opti < args.length) {
9224 String opt = args[opti];
9225 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
9226 break;
9227 }
9228 opti++;
9229 if ("-a".equals(opt)) {
9230 dumpAll = true;
9231 } else if ("-h".equals(opt)) {
9232 pw.println("meminfo dump options: [-a] [process]");
9233 pw.println(" -a: include all available information for each process.");
9234 pw.println("If [process] is specified it can be the name or ");
9235 pw.println("pid of a specific process to dump.");
9236 return;
9237 } else {
9238 pw.println("Unknown argument: " + opt + "; use -h for help");
9239 }
9240 }
9241
9242 ArrayList<ProcessRecord> procs = collectProcesses(pw, opti, args);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009243 if (procs == null) {
9244 return;
9245 }
9246
Dianne Hackborn6447ca32009-04-07 19:50:08 -07009247 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009248 long uptime = SystemClock.uptimeMillis();
9249 long realtime = SystemClock.elapsedRealtime();
Dianne Hackbornb437e092011-08-05 17:50:29 -07009250
9251 if (procs.size() == 1 || isCheckinRequest) {
9252 dumpAll = true;
9253 }
9254
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009255 if (isCheckinRequest) {
9256 // short checkin version
9257 pw.println(uptime + "," + realtime);
9258 pw.flush();
9259 } else {
9260 pw.println("Applications Memory Usage (kB):");
9261 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
9262 }
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009263
Dianne Hackbornb437e092011-08-05 17:50:29 -07009264 String[] innerArgs = new String[args.length-opti];
9265 System.arraycopy(args, opti, innerArgs, 0, args.length-opti);
9266
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009267 ArrayList<MemItem> procMems = new ArrayList<MemItem>();
9268 long nativePss=0, dalvikPss=0, otherPss=0;
9269 long[] miscPss = new long[Debug.MemoryInfo.NUM_OTHER_STATS];
9270
Dianne Hackbornb437e092011-08-05 17:50:29 -07009271 final int[] oomAdj = new int[] {
Dianne Hackborn7d608422011-08-07 16:24:18 -07009272 ProcessList.SYSTEM_ADJ, ProcessList.CORE_SERVER_ADJ, ProcessList.FOREGROUND_APP_ADJ,
9273 ProcessList.VISIBLE_APP_ADJ, ProcessList.PERCEPTIBLE_APP_ADJ, ProcessList.HEAVY_WEIGHT_APP_ADJ,
9274 ProcessList.BACKUP_APP_ADJ, ProcessList.SECONDARY_SERVER_ADJ, ProcessList.HOME_APP_ADJ, ProcessList.EMPTY_APP_ADJ
Dianne Hackbornb437e092011-08-05 17:50:29 -07009275 };
9276 final String[] oomLabel = new String[] {
9277 "System", "Persistent", "Foreground",
9278 "Visible", "Perceptible", "Heavy Weight",
9279 "Backup", "Services", "Home", "Background"
9280 };
9281 long oomPss[] = new long[oomLabel.length];
Dianne Hackborna4bacb82011-08-24 15:12:38 -07009282 ArrayList<MemItem>[] oomProcs = (ArrayList<MemItem>[])new ArrayList[oomLabel.length];
Dianne Hackbornb437e092011-08-05 17:50:29 -07009283
9284 long totalPss = 0;
9285
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009286 for (int i = procs.size() - 1 ; i >= 0 ; i--) {
9287 ProcessRecord r = procs.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009288 if (r.thread != null) {
Dianne Hackbornb437e092011-08-05 17:50:29 -07009289 if (!isCheckinRequest && dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009290 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
9291 pw.flush();
9292 }
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009293 Debug.MemoryInfo mi = null;
Dianne Hackbornb437e092011-08-05 17:50:29 -07009294 if (dumpAll) {
9295 try {
9296 mi = r.thread.dumpMemInfo(fd, isCheckinRequest, dumpAll, innerArgs);
9297 } catch (RemoteException e) {
9298 if (!isCheckinRequest) {
9299 pw.println("Got RemoteException!");
9300 pw.flush();
9301 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009302 }
Dianne Hackbornb437e092011-08-05 17:50:29 -07009303 } else {
9304 mi = new Debug.MemoryInfo();
9305 Debug.getMemoryInfo(r.pid, mi);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009306 }
Dianne Hackbornb437e092011-08-05 17:50:29 -07009307
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009308 if (!isCheckinRequest && mi != null) {
Dianne Hackbornb437e092011-08-05 17:50:29 -07009309 long myTotalPss = mi.getTotalPss();
9310 totalPss += myTotalPss;
Dianne Hackborna4bacb82011-08-24 15:12:38 -07009311 MemItem pssItem = new MemItem(r.processName + " (pid " + r.pid + ")",
9312 myTotalPss);
9313 procMems.add(pssItem);
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009314
9315 nativePss += mi.nativePss;
9316 dalvikPss += mi.dalvikPss;
9317 otherPss += mi.otherPss;
9318 for (int j=0; j<Debug.MemoryInfo.NUM_OTHER_STATS; j++) {
9319 long mem = mi.getOtherPss(j);
9320 miscPss[j] += mem;
9321 otherPss -= mem;
9322 }
Dianne Hackbornb437e092011-08-05 17:50:29 -07009323
9324 for (int oomIndex=0; oomIndex<oomPss.length; oomIndex++) {
9325 if (r.setAdj <= oomAdj[oomIndex] || oomIndex == (oomPss.length-1)) {
9326 oomPss[oomIndex] += myTotalPss;
Dianne Hackborna4bacb82011-08-24 15:12:38 -07009327 if (oomProcs[oomIndex] == null) {
9328 oomProcs[oomIndex] = new ArrayList<MemItem>();
9329 }
9330 oomProcs[oomIndex].add(pssItem);
Dianne Hackbornb437e092011-08-05 17:50:29 -07009331 break;
9332 }
9333 }
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009334 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009335 }
9336 }
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009337
9338 if (!isCheckinRequest && procs.size() > 1) {
9339 ArrayList<MemItem> catMems = new ArrayList<MemItem>();
9340
9341 catMems.add(new MemItem("Native", nativePss));
9342 catMems.add(new MemItem("Dalvik", dalvikPss));
9343 catMems.add(new MemItem("Unknown", otherPss));
9344 for (int j=0; j<Debug.MemoryInfo.NUM_OTHER_STATS; j++) {
9345 catMems.add(new MemItem(Debug.MemoryInfo.getOtherLabel(j), miscPss[j]));
9346 }
9347
Dianne Hackbornb437e092011-08-05 17:50:29 -07009348 ArrayList<MemItem> oomMems = new ArrayList<MemItem>();
9349 for (int j=0; j<oomPss.length; j++) {
9350 if (oomPss[j] != 0) {
Dianne Hackborna4bacb82011-08-24 15:12:38 -07009351 MemItem item = new MemItem(oomLabel[j], oomPss[j]);
9352 item.subitems = oomProcs[j];
9353 oomMems.add(item);
Dianne Hackbornb437e092011-08-05 17:50:29 -07009354 }
9355 }
9356
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009357 pw.println();
9358 pw.println("Total PSS by process:");
Dianne Hackbornb437e092011-08-05 17:50:29 -07009359 dumpMemItems(pw, " ", procMems, true);
9360 pw.println();
9361 pw.println("Total PSS by OOM adjustment:");
9362 dumpMemItems(pw, " ", oomMems, false);
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009363 pw.println();
9364 pw.println("Total PSS by category:");
Dianne Hackbornb437e092011-08-05 17:50:29 -07009365 dumpMemItems(pw, " ", catMems, true);
9366 pw.println();
9367 pw.print("Total PSS: "); pw.print(totalPss); pw.println(" Kb");
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009368 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009369 }
9370
9371 /**
9372 * Searches array of arguments for the specified string
9373 * @param args array of argument strings
9374 * @param value value to search for
9375 * @return true if the value is contained in the array
9376 */
9377 private static boolean scanArgs(String[] args, String value) {
9378 if (args != null) {
9379 for (String arg : args) {
9380 if (value.equals(arg)) {
9381 return true;
9382 }
9383 }
9384 }
9385 return false;
9386 }
9387
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009388 private final void killServicesLocked(ProcessRecord app,
9389 boolean allowRestart) {
9390 // Report disconnected services.
9391 if (false) {
9392 // XXX we are letting the client link to the service for
9393 // death notifications.
9394 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009395 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009396 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009397 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009398 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009399 Iterator<ArrayList<ConnectionRecord>> jt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009400 = r.connections.values().iterator();
9401 while (jt.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009402 ArrayList<ConnectionRecord> cl = jt.next();
9403 for (int i=0; i<cl.size(); i++) {
9404 ConnectionRecord c = cl.get(i);
9405 if (c.binding.client != app) {
9406 try {
9407 //c.conn.connected(r.className, null);
9408 } catch (Exception e) {
9409 // todo: this should be asynchronous!
9410 Slog.w(TAG, "Exception thrown disconnected servce "
9411 + r.shortName
9412 + " from app " + app.processName, e);
9413 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009414 }
9415 }
9416 }
9417 }
9418 }
9419 }
9420 }
9421
9422 // Clean up any connections this application has to other services.
9423 if (app.connections.size() > 0) {
9424 Iterator<ConnectionRecord> it = app.connections.iterator();
9425 while (it.hasNext()) {
9426 ConnectionRecord r = it.next();
9427 removeConnectionLocked(r, app, null);
9428 }
9429 }
9430 app.connections.clear();
9431
9432 if (app.services.size() != 0) {
9433 // Any services running in the application need to be placed
9434 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07009435 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009436 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009437 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009438 synchronized (sr.stats.getBatteryStats()) {
9439 sr.stats.stopLaunchedLocked();
9440 }
9441 sr.app = null;
9442 sr.executeNesting = 0;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009443 if (mStoppingServices.remove(sr)) {
9444 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
9445 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009446
9447 boolean hasClients = sr.bindings.size() > 0;
9448 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009449 Iterator<IntentBindRecord> bindings
9450 = sr.bindings.values().iterator();
9451 while (bindings.hasNext()) {
9452 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -08009453 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009454 + ": shouldUnbind=" + b.hasBound);
9455 b.binder = null;
9456 b.requested = b.received = b.hasBound = false;
9457 }
9458 }
9459
Dianne Hackborn070783f2010-12-29 16:46:28 -08009460 if (sr.crashCount >= 2 && (sr.serviceInfo.applicationInfo.flags
9461 &ApplicationInfo.FLAG_PERSISTENT) == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009462 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009463 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -08009464 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009465 sr.crashCount, sr.shortName, app.pid);
9466 bringDownServiceLocked(sr, true);
9467 } else if (!allowRestart) {
9468 bringDownServiceLocked(sr, true);
9469 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009470 boolean canceled = scheduleServiceRestartLocked(sr, true);
9471
9472 // Should the service remain running? Note that in the
9473 // extreme case of so many attempts to deliver a command
Dianne Hackborn130b0d22011-07-26 22:07:48 -07009474 // that it failed we also will stop it here.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -07009475 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
9476 if (sr.pendingStarts.size() == 0) {
9477 sr.startRequested = false;
9478 if (!hasClients) {
9479 // Whoops, no reason to restart!
9480 bringDownServiceLocked(sr, true);
9481 }
9482 }
9483 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009484 }
9485 }
9486
9487 if (!allowRestart) {
9488 app.services.clear();
9489 }
9490 }
9491
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009492 // Make sure we have no more records on the stopping list.
9493 int i = mStoppingServices.size();
9494 while (i > 0) {
9495 i--;
9496 ServiceRecord sr = mStoppingServices.get(i);
9497 if (sr.app == app) {
9498 mStoppingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009499 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009500 }
9501 }
9502
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009503 app.executingServices.clear();
9504 }
9505
9506 private final void removeDyingProviderLocked(ProcessRecord proc,
9507 ContentProviderRecord cpr) {
9508 synchronized (cpr) {
9509 cpr.launchingApp = null;
9510 cpr.notifyAll();
9511 }
9512
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07009513 mProvidersByClass.remove(cpr.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009514 String names[] = cpr.info.authority.split(";");
9515 for (int j = 0; j < names.length; j++) {
9516 mProvidersByName.remove(names[j]);
9517 }
9518
9519 Iterator<ProcessRecord> cit = cpr.clients.iterator();
9520 while (cit.hasNext()) {
9521 ProcessRecord capp = cit.next();
9522 if (!capp.persistent && capp.thread != null
9523 && capp.pid != 0
9524 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07009525 Slog.i(TAG, "Kill " + capp.processName
9526 + " (pid " + capp.pid + "): provider " + cpr.info.name
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07009527 + " in dying process " + (proc != null ? proc.processName : "??"));
Dianne Hackborn8633e682010-04-22 16:03:41 -07009528 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07009529 capp.processName, capp.setAdj, "dying provider "
9530 + cpr.name.toShortString());
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07009531 Process.killProcessQuiet(capp.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009532 }
9533 }
9534
9535 mLaunchingProviders.remove(cpr);
9536 }
9537
9538 /**
9539 * Main code for cleaning up a process when it has gone away. This is
9540 * called both as a result of the process dying, or directly when stopping
9541 * a process when running in single process mode.
9542 */
9543 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
Dianne Hackborn130b0d22011-07-26 22:07:48 -07009544 boolean restarting, boolean allowRestart, int index) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009545 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08009546 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009547 }
9548
Dianne Hackborn36124872009-10-08 16:22:03 -07009549 mProcessesToGc.remove(app);
9550
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009551 // Dismiss any open dialogs.
9552 if (app.crashDialog != null) {
9553 app.crashDialog.dismiss();
9554 app.crashDialog = null;
9555 }
9556 if (app.anrDialog != null) {
9557 app.anrDialog.dismiss();
9558 app.anrDialog = null;
9559 }
9560 if (app.waitDialog != null) {
9561 app.waitDialog.dismiss();
9562 app.waitDialog = null;
9563 }
9564
9565 app.crashing = false;
9566 app.notResponding = false;
9567
9568 app.resetPackageList();
Dianne Hackborn1b64e0d2011-07-17 15:23:59 -07009569 app.unlinkDeathRecipient();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009570 app.thread = null;
9571 app.forcingToForeground = null;
9572 app.foregroundServices = false;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07009573 app.foregroundActivities = false;
Dianne Hackbornf0754f5b2011-07-21 16:02:07 -07009574 app.hasShownUi = false;
Dianne Hackbornc68c9132011-07-29 01:25:18 -07009575 app.hasAboveClient = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009576
Dianne Hackborn130b0d22011-07-26 22:07:48 -07009577 killServicesLocked(app, allowRestart);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009578
9579 boolean restart = false;
9580
9581 int NL = mLaunchingProviders.size();
9582
9583 // Remove published content providers.
9584 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009585 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009586 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009587 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009588 cpr.provider = null;
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07009589 cpr.proc = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009590
9591 // See if someone is waiting for this provider... in which
9592 // case we don't remove it, but just let it restart.
9593 int i = 0;
Dianne Hackborn130b0d22011-07-26 22:07:48 -07009594 if (!app.bad && allowRestart) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009595 for (; i<NL; i++) {
9596 if (mLaunchingProviders.get(i) == cpr) {
9597 restart = true;
9598 break;
9599 }
9600 }
9601 } else {
9602 i = NL;
9603 }
9604
9605 if (i >= NL) {
9606 removeDyingProviderLocked(app, cpr);
9607 NL = mLaunchingProviders.size();
9608 }
9609 }
9610 app.pubProviders.clear();
9611 }
9612
Dianne Hackbornf670ef72009-11-16 13:59:16 -08009613 // Take care of any launching providers waiting for this process.
9614 if (checkAppInLaunchingProvidersLocked(app, false)) {
9615 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009616 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08009617
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009618 // Unregister from connected content providers.
9619 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07009620 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009621 while (it.hasNext()) {
9622 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
9623 cpr.clients.remove(app);
9624 }
9625 app.conProviders.clear();
9626 }
9627
Dianne Hackbornde42bb62009-08-05 12:26:15 -07009628 // At this point there may be remaining entries in mLaunchingProviders
9629 // where we were the only one waiting, so they are no longer of use.
9630 // Look for these and clean up if found.
9631 // XXX Commented out for now. Trying to figure out a way to reproduce
9632 // the actual situation to identify what is actually going on.
9633 if (false) {
9634 for (int i=0; i<NL; i++) {
9635 ContentProviderRecord cpr = (ContentProviderRecord)
9636 mLaunchingProviders.get(i);
9637 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
9638 synchronized (cpr) {
9639 cpr.launchingApp = null;
9640 cpr.notifyAll();
9641 }
9642 }
9643 }
9644 }
9645
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009646 skipCurrentReceiverLocked(app);
9647
9648 // Unregister any receivers.
9649 if (app.receivers.size() > 0) {
9650 Iterator<ReceiverList> it = app.receivers.iterator();
9651 while (it.hasNext()) {
9652 removeReceiverLocked(it.next());
9653 }
9654 app.receivers.clear();
9655 }
9656
Christopher Tate181fafa2009-05-14 11:12:14 -07009657 // If the app is undergoing backup, tell the backup manager about it
9658 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009659 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -07009660 try {
9661 IBackupManager bm = IBackupManager.Stub.asInterface(
9662 ServiceManager.getService(Context.BACKUP_SERVICE));
9663 bm.agentDisconnected(app.info.packageName);
9664 } catch (RemoteException e) {
9665 // can't happen; backup manager is local
9666 }
9667 }
9668
Jeff Sharkey287bd832011-05-28 19:36:26 -07009669 mHandler.obtainMessage(DISPATCH_PROCESS_DIED, app.pid, app.info.uid, null).sendToTarget();
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07009670
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009671 // If the caller is restarting this app, then leave it in its
9672 // current lists and let the caller take care of it.
9673 if (restarting) {
9674 return;
9675 }
9676
9677 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009678 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009679 "Removing non-persistent process during cleanup: " + app);
9680 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07009681 if (mHeavyWeightProcess == app) {
9682 mHeavyWeightProcess = null;
9683 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
9684 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009685 } else if (!app.removed) {
9686 // This app is persistent, so we need to keep its record around.
9687 // If it is not already on the pending app list, add it there
9688 // and start a new process for it.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009689 if (mPersistentStartingProcesses.indexOf(app) < 0) {
9690 mPersistentStartingProcesses.add(app);
9691 restart = true;
9692 }
9693 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07009694 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
9695 "Clean-up removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009696 mProcessesOnHold.remove(app);
9697
The Android Open Source Project4df24232009-03-05 14:34:35 -08009698 if (app == mHomeProcess) {
9699 mHomeProcess = null;
9700 }
9701
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009702 if (restart) {
9703 // We have components that still need to be running in the
9704 // process, so re-launch it.
9705 mProcessNames.put(app.processName, app.info.uid, app);
9706 startProcessLocked(app, "restart", app.processName);
9707 } else if (app.pid > 0 && app.pid != MY_PID) {
9708 // Goodbye!
9709 synchronized (mPidsSelfLocked) {
9710 mPidsSelfLocked.remove(app.pid);
9711 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
9712 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009713 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009714 }
9715 }
9716
Dianne Hackbornf670ef72009-11-16 13:59:16 -08009717 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
9718 // Look through the content providers we are waiting to have launched,
9719 // and if any run in this process then either schedule a restart of
9720 // the process or kill the client waiting for it if this process has
9721 // gone bad.
9722 int NL = mLaunchingProviders.size();
9723 boolean restart = false;
9724 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009725 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08009726 if (cpr.launchingApp == app) {
9727 if (!alwaysBad && !app.bad) {
9728 restart = true;
9729 } else {
9730 removeDyingProviderLocked(app, cpr);
9731 NL = mLaunchingProviders.size();
9732 }
9733 }
9734 }
9735 return restart;
9736 }
9737
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009738 // =========================================================
9739 // SERVICES
9740 // =========================================================
9741
9742 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
9743 ActivityManager.RunningServiceInfo info =
9744 new ActivityManager.RunningServiceInfo();
9745 info.service = r.name;
9746 if (r.app != null) {
9747 info.pid = r.app.pid;
9748 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -07009749 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009750 info.process = r.processName;
9751 info.foreground = r.isForeground;
9752 info.activeSince = r.createTime;
9753 info.started = r.startRequested;
9754 info.clientCount = r.connections.size();
9755 info.crashCount = r.crashCount;
9756 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07009757 if (r.isForeground) {
9758 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
9759 }
9760 if (r.startRequested) {
9761 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
9762 }
Dan Egnor42471dd2010-01-07 17:25:22 -08009763 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -07009764 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
9765 }
9766 if (r.app != null && r.app.persistent) {
9767 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
9768 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009769
9770 for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
9771 for (int i=0; i<connl.size(); i++) {
9772 ConnectionRecord conn = connl.get(i);
9773 if (conn.clientLabel != 0) {
9774 info.clientPackage = conn.binding.client.info.packageName;
9775 info.clientLabel = conn.clientLabel;
9776 return info;
9777 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009778 }
9779 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009780 return info;
9781 }
9782
9783 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
9784 int flags) {
9785 synchronized (this) {
9786 ArrayList<ActivityManager.RunningServiceInfo> res
9787 = new ArrayList<ActivityManager.RunningServiceInfo>();
9788
9789 if (mServices.size() > 0) {
9790 Iterator<ServiceRecord> it = mServices.values().iterator();
9791 while (it.hasNext() && res.size() < maxNum) {
9792 res.add(makeRunningServiceInfoLocked(it.next()));
9793 }
9794 }
9795
9796 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
9797 ServiceRecord r = mRestartingServices.get(i);
9798 ActivityManager.RunningServiceInfo info =
9799 makeRunningServiceInfoLocked(r);
9800 info.restarting = r.nextRestartTime;
9801 res.add(info);
9802 }
9803
9804 return res;
9805 }
9806 }
9807
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009808 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
9809 synchronized (this) {
9810 ServiceRecord r = mServices.get(name);
9811 if (r != null) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009812 for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
9813 for (int i=0; i<conn.size(); i++) {
9814 if (conn.get(i).clientIntent != null) {
9815 return conn.get(i).clientIntent;
9816 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07009817 }
9818 }
9819 }
9820 }
9821 return null;
9822 }
9823
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009824 private final ServiceRecord findServiceLocked(ComponentName name,
9825 IBinder token) {
9826 ServiceRecord r = mServices.get(name);
9827 return r == token ? r : null;
9828 }
9829
9830 private final class ServiceLookupResult {
9831 final ServiceRecord record;
9832 final String permission;
9833
9834 ServiceLookupResult(ServiceRecord _record, String _permission) {
9835 record = _record;
9836 permission = _permission;
9837 }
9838 };
9839
9840 private ServiceLookupResult findServiceLocked(Intent service,
9841 String resolvedType) {
9842 ServiceRecord r = null;
9843 if (service.getComponent() != null) {
9844 r = mServices.get(service.getComponent());
9845 }
9846 if (r == null) {
9847 Intent.FilterComparison filter = new Intent.FilterComparison(service);
9848 r = mServicesByIntent.get(filter);
9849 }
9850
9851 if (r == null) {
9852 try {
9853 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009854 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009855 service, resolvedType, 0);
9856 ServiceInfo sInfo =
9857 rInfo != null ? rInfo.serviceInfo : null;
9858 if (sInfo == null) {
9859 return null;
9860 }
9861
9862 ComponentName name = new ComponentName(
9863 sInfo.applicationInfo.packageName, sInfo.name);
9864 r = mServices.get(name);
9865 } catch (RemoteException ex) {
9866 // pm is in same process, this will never happen.
9867 }
9868 }
9869 if (r != null) {
9870 int callingPid = Binder.getCallingPid();
9871 int callingUid = Binder.getCallingUid();
9872 if (checkComponentPermission(r.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009873 callingPid, callingUid, r.appInfo.uid, r.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009874 != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009875 if (!r.exported) {
9876 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
9877 + " from pid=" + callingPid
9878 + ", uid=" + callingUid
9879 + " that is not exported from uid " + r.appInfo.uid);
9880 return new ServiceLookupResult(null, "not exported from uid "
9881 + r.appInfo.uid);
9882 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009883 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009884 + " from pid=" + callingPid
9885 + ", uid=" + callingUid
9886 + " requires " + r.permission);
9887 return new ServiceLookupResult(null, r.permission);
9888 }
9889 return new ServiceLookupResult(r, null);
9890 }
9891 return null;
9892 }
9893
9894 private class ServiceRestarter implements Runnable {
9895 private ServiceRecord mService;
9896
9897 void setService(ServiceRecord service) {
9898 mService = service;
9899 }
9900
9901 public void run() {
9902 synchronized(ActivityManagerService.this) {
9903 performServiceRestartLocked(mService);
9904 }
9905 }
9906 }
9907
9908 private ServiceLookupResult retrieveServiceLocked(Intent service,
9909 String resolvedType, int callingPid, int callingUid) {
9910 ServiceRecord r = null;
9911 if (service.getComponent() != null) {
9912 r = mServices.get(service.getComponent());
9913 }
9914 Intent.FilterComparison filter = new Intent.FilterComparison(service);
9915 r = mServicesByIntent.get(filter);
9916 if (r == null) {
9917 try {
9918 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07009919 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -07009920 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009921 ServiceInfo sInfo =
9922 rInfo != null ? rInfo.serviceInfo : null;
9923 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009924 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009925 ": not found");
9926 return null;
9927 }
9928
9929 ComponentName name = new ComponentName(
9930 sInfo.applicationInfo.packageName, sInfo.name);
9931 r = mServices.get(name);
9932 if (r == null) {
9933 filter = new Intent.FilterComparison(service.cloneFilter());
9934 ServiceRestarter res = new ServiceRestarter();
9935 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
9936 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
9937 synchronized (stats) {
9938 ss = stats.getServiceStatsLocked(
9939 sInfo.applicationInfo.uid, sInfo.packageName,
9940 sInfo.name);
9941 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -08009942 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009943 res.setService(r);
9944 mServices.put(name, r);
9945 mServicesByIntent.put(filter, r);
9946
9947 // Make sure this component isn't in the pending list.
9948 int N = mPendingServices.size();
9949 for (int i=0; i<N; i++) {
9950 ServiceRecord pr = mPendingServices.get(i);
9951 if (pr.name.equals(name)) {
9952 mPendingServices.remove(i);
9953 i--;
9954 N--;
9955 }
9956 }
9957 }
9958 } catch (RemoteException ex) {
9959 // pm is in same process, this will never happen.
9960 }
9961 }
9962 if (r != null) {
9963 if (checkComponentPermission(r.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009964 callingPid, callingUid, r.appInfo.uid, r.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009965 != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009966 if (!r.exported) {
9967 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
9968 + " from pid=" + callingPid
9969 + ", uid=" + callingUid
9970 + " that is not exported from uid " + r.appInfo.uid);
9971 return new ServiceLookupResult(null, "not exported from uid "
9972 + r.appInfo.uid);
9973 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009974 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08009975 + " from pid=" + callingPid
9976 + ", uid=" + callingUid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009977 + " requires " + r.permission);
9978 return new ServiceLookupResult(null, r.permission);
9979 }
9980 return new ServiceLookupResult(r, null);
9981 }
9982 return null;
9983 }
9984
Dianne Hackborn287952c2010-09-22 22:34:31 -07009985 private final void bumpServiceExecutingLocked(ServiceRecord r, String why) {
9986 if (DEBUG_SERVICE) Log.v(TAG, ">>> EXECUTING "
9987 + why + " of " + r + " in app " + r.app);
9988 else if (DEBUG_SERVICE_EXECUTING) Log.v(TAG, ">>> EXECUTING "
9989 + why + " of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009990 long now = SystemClock.uptimeMillis();
9991 if (r.executeNesting == 0 && r.app != null) {
9992 if (r.app.executingServices.size() == 0) {
9993 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
9994 msg.obj = r.app;
9995 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
9996 }
9997 r.app.executingServices.add(r);
9998 }
9999 r.executeNesting++;
10000 r.executingStart = now;
10001 }
10002
10003 private final void sendServiceArgsLocked(ServiceRecord r,
10004 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010005 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010006 if (N == 0) {
10007 return;
10008 }
10009
Dianne Hackborn39792d22010-08-19 18:01:52 -070010010 while (r.pendingStarts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010011 try {
Dianne Hackborn39792d22010-08-19 18:01:52 -070010012 ServiceRecord.StartItem si = r.pendingStarts.remove(0);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010013 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
10014 + r + " " + r.intent + " args=" + si.intent);
Dianne Hackborn3a28f222011-03-01 12:25:54 -080010015 if (si.intent == null && N > 1) {
10016 // If somehow we got a dummy null intent in the middle,
10017 // then skip it. DO NOT skip a null intent when it is
10018 // the only one in the list -- this is to support the
10019 // onStartCommand(null) case.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010020 continue;
10021 }
Dianne Hackborn39792d22010-08-19 18:01:52 -070010022 si.deliveredTime = SystemClock.uptimeMillis();
10023 r.deliveredStarts.add(si);
10024 si.deliveryCount++;
Dianne Hackborn3a28f222011-03-01 12:25:54 -080010025 if (si.targetPermissionUid >= 0 && si.intent != null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -070010026 grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
Dianne Hackborn7e269642010-08-25 19:50:20 -070010027 r.packageName, si.intent, si.getUriPermissionsLocked());
Dianne Hackborn39792d22010-08-19 18:01:52 -070010028 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070010029 bumpServiceExecutingLocked(r, "start");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010030 if (!oomAdjusted) {
10031 oomAdjusted = true;
10032 updateOomAdjLocked(r.app);
10033 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010034 int flags = 0;
10035 if (si.deliveryCount > 0) {
10036 flags |= Service.START_FLAG_RETRY;
10037 }
10038 if (si.doneExecutingCount > 0) {
10039 flags |= Service.START_FLAG_REDELIVERY;
10040 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010041 r.app.thread.scheduleServiceArgs(r, si.taskRemoved, si.id, flags, si.intent);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010042 } catch (RemoteException e) {
10043 // Remote process gone... we'll let the normal cleanup take
10044 // care of this.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010045 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010046 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010047 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010048 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010049 break;
10050 }
10051 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010052 }
10053
10054 private final boolean requestServiceBindingLocked(ServiceRecord r,
10055 IntentBindRecord i, boolean rebind) {
10056 if (r.app == null || r.app.thread == null) {
10057 // If service is not currently running, can't yet bind.
10058 return false;
10059 }
10060 if ((!i.requested || rebind) && i.apps.size() > 0) {
10061 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010062 bumpServiceExecutingLocked(r, "bind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010063 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
10064 if (!rebind) {
10065 i.requested = true;
10066 }
10067 i.hasBound = true;
10068 i.doRebind = false;
10069 } catch (RemoteException e) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010070 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010071 return false;
10072 }
10073 }
10074 return true;
10075 }
10076
10077 private final void requestServiceBindingsLocked(ServiceRecord r) {
10078 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
10079 while (bindings.hasNext()) {
10080 IntentBindRecord i = bindings.next();
10081 if (!requestServiceBindingLocked(r, i, false)) {
10082 break;
10083 }
10084 }
10085 }
10086
10087 private final void realStartServiceLocked(ServiceRecord r,
10088 ProcessRecord app) throws RemoteException {
10089 if (app.thread == null) {
10090 throw new RemoteException();
10091 }
10092
10093 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -070010094 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010095
10096 app.services.add(r);
Dianne Hackborn287952c2010-09-22 22:34:31 -070010097 bumpServiceExecutingLocked(r, "create");
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010098 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010099
10100 boolean created = false;
10101 try {
Dianne Hackborna33e3f72009-09-29 17:28:24 -070010102 mStringBuilder.setLength(0);
Dianne Hackborn90c52de2011-09-23 12:57:44 -070010103 r.intent.getIntent().toShortString(mStringBuilder, true, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010104 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010105 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -070010106 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010107 synchronized (r.stats.getBatteryStats()) {
10108 r.stats.startLaunchedLocked();
10109 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070010110 ensurePackageDexOpt(r.serviceInfo.packageName);
Dianne Hackborne2515ee2011-04-27 18:52:56 -040010111 app.thread.scheduleCreateService(r, r.serviceInfo,
10112 compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo));
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010113 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010114 created = true;
10115 } finally {
10116 if (!created) {
10117 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010118 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010119 }
10120 }
10121
10122 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010123
10124 // If the service is in the started state, and there are no
10125 // pending arguments, then fake up one so its onStartCommand() will
10126 // be called.
10127 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010128 r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
10129 null, -1));
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010130 }
10131
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010132 sendServiceArgsLocked(r, true);
10133 }
10134
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010135 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
10136 boolean allowCancel) {
10137 boolean canceled = false;
10138
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010139 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010140 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -070010141 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010142
Dianne Hackborn070783f2010-12-29 16:46:28 -080010143 if ((r.serviceInfo.applicationInfo.flags
10144 &ApplicationInfo.FLAG_PERSISTENT) != 0) {
10145 minDuration /= 4;
10146 }
10147
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010148 // Any delivered but not yet finished starts should be put back
10149 // on the pending list.
10150 final int N = r.deliveredStarts.size();
10151 if (N > 0) {
10152 for (int i=N-1; i>=0; i--) {
10153 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
Dianne Hackborn39792d22010-08-19 18:01:52 -070010154 si.removeUriPermissionsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010155 if (si.intent == null) {
10156 // We'll generate this again if needed.
10157 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
10158 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
10159 r.pendingStarts.add(0, si);
10160 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
10161 dur *= 2;
10162 if (minDuration < dur) minDuration = dur;
10163 if (resetTime < dur) resetTime = dur;
10164 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010165 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010166 + r.name);
10167 canceled = true;
10168 }
10169 }
10170 r.deliveredStarts.clear();
10171 }
10172
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010173 r.totalRestartCount++;
10174 if (r.restartDelay == 0) {
10175 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010176 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010177 } else {
10178 // If it has been a "reasonably long time" since the service
10179 // was started, then reset our restart duration back to
10180 // the beginning, so we don't infinitely increase the duration
10181 // on a service that just occasionally gets killed (which is
10182 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010183 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010184 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010185 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010186 } else {
Dianne Hackborn070783f2010-12-29 16:46:28 -080010187 if ((r.serviceInfo.applicationInfo.flags
10188 &ApplicationInfo.FLAG_PERSISTENT) != 0) {
10189 // Services in peristent processes will restart much more
10190 // quickly, since they are pretty important. (Think SystemUI).
10191 r.restartDelay += minDuration/2;
10192 } else {
10193 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
10194 if (r.restartDelay < minDuration) {
10195 r.restartDelay = minDuration;
10196 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010197 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010198 }
10199 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010200
10201 r.nextRestartTime = now + r.restartDelay;
10202
10203 // Make sure that we don't end up restarting a bunch of services
10204 // all at the same time.
10205 boolean repeat;
10206 do {
10207 repeat = false;
10208 for (int i=mRestartingServices.size()-1; i>=0; i--) {
10209 ServiceRecord r2 = mRestartingServices.get(i);
10210 if (r2 != r && r.nextRestartTime
10211 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
10212 && r.nextRestartTime
10213 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
10214 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
10215 r.restartDelay = r.nextRestartTime - now;
10216 repeat = true;
10217 break;
10218 }
10219 }
10220 } while (repeat);
10221
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010222 if (!mRestartingServices.contains(r)) {
10223 mRestartingServices.add(r);
10224 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010225
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010226 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010227
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010228 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010229 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010230 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010231 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010232 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -080010233 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010234 r.shortName, r.restartDelay);
10235
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010236 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010237 }
10238
10239 final void performServiceRestartLocked(ServiceRecord r) {
10240 if (!mRestartingServices.contains(r)) {
10241 return;
10242 }
10243 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
10244 }
10245
10246 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
10247 if (r.restartDelay == 0) {
10248 return false;
10249 }
10250 r.resetRestartCounter();
10251 mRestartingServices.remove(r);
10252 mHandler.removeCallbacks(r.restarter);
10253 return true;
10254 }
10255
10256 private final boolean bringUpServiceLocked(ServiceRecord r,
10257 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010258 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010259 //r.dump(" ");
10260
Dianne Hackborn36124872009-10-08 16:22:03 -070010261 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010262 sendServiceArgsLocked(r, false);
10263 return true;
10264 }
10265
10266 if (!whileRestarting && r.restartDelay > 0) {
10267 // If waiting for a restart, then do nothing.
10268 return true;
10269 }
10270
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010271 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010272
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010273 // We are now bringing the service up, so no longer in the
10274 // restarting state.
10275 mRestartingServices.remove(r);
10276
Dianne Hackborne7f97212011-02-24 14:40:20 -080010277 // Service is now being launched, its package can't be stopped.
10278 try {
10279 AppGlobals.getPackageManager().setPackageStoppedState(
10280 r.packageName, false);
10281 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -080010282 } catch (IllegalArgumentException e) {
10283 Slog.w(TAG, "Failed trying to unstop package "
10284 + r.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -080010285 }
10286
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010287 final String appName = r.processName;
10288 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
10289 if (app != null && app.thread != null) {
10290 try {
Dianne Hackborn6c418d52011-06-29 14:05:33 -070010291 app.addPackage(r.appInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010292 realStartServiceLocked(r, app);
10293 return true;
10294 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010295 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010296 }
10297
10298 // If a dead object exception was thrown -- fall through to
10299 // restart the application.
10300 }
10301
Dianne Hackborn36124872009-10-08 16:22:03 -070010302 // Not running -- get it started, and enqueue this service record
10303 // to be executed when the app comes up.
10304 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
10305 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010306 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -070010307 + r.appInfo.packageName + "/"
10308 + r.appInfo.uid + " for service "
10309 + r.intent.getIntent() + ": process is bad");
10310 bringDownServiceLocked(r, true);
10311 return false;
10312 }
10313
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010314 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010315 mPendingServices.add(r);
10316 }
Dianne Hackborn36124872009-10-08 16:22:03 -070010317
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010318 return true;
10319 }
10320
10321 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010322 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010323 //r.dump(" ");
10324
10325 // Does it still need to run?
10326 if (!force && r.startRequested) {
10327 return;
10328 }
10329 if (r.connections.size() > 0) {
10330 if (!force) {
10331 // XXX should probably keep a count of the number of auto-create
10332 // connections directly in the service.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010333 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010334 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010335 ArrayList<ConnectionRecord> cr = it.next();
10336 for (int i=0; i<cr.size(); i++) {
10337 if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
10338 return;
10339 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010340 }
10341 }
10342 }
10343
10344 // Report to all of the connections that the service is no longer
10345 // available.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010346 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010347 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010348 ArrayList<ConnectionRecord> c = it.next();
10349 for (int i=0; i<c.size(); i++) {
Dianne Hackborn130b0d22011-07-26 22:07:48 -070010350 ConnectionRecord cr = c.get(i);
10351 // There is still a connection to the service that is
10352 // being brought down. Mark it as dead.
10353 cr.serviceDead = true;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010354 try {
Dianne Hackborn130b0d22011-07-26 22:07:48 -070010355 cr.conn.connected(r.name, null);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010356 } catch (Exception e) {
10357 Slog.w(TAG, "Failure disconnecting service " + r.name +
10358 " to connection " + c.get(i).conn.asBinder() +
10359 " (in " + c.get(i).binding.client.processName + ")", e);
10360 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010361 }
10362 }
10363 }
10364
10365 // Tell the service that it has been unbound.
10366 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
10367 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
10368 while (it.hasNext()) {
10369 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010370 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010371 + ": hasBound=" + ibr.hasBound);
10372 if (r.app != null && r.app.thread != null && ibr.hasBound) {
10373 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010374 bumpServiceExecutingLocked(r, "bring down unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010375 updateOomAdjLocked(r.app);
10376 ibr.hasBound = false;
10377 r.app.thread.scheduleUnbindService(r,
10378 ibr.intent.getIntent());
10379 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010380 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010381 + r.shortName, e);
10382 serviceDoneExecutingLocked(r, true);
10383 }
10384 }
10385 }
10386 }
10387
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010388 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010389 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010390 System.identityHashCode(r), r.shortName,
10391 (r.app != null) ? r.app.pid : -1);
10392
10393 mServices.remove(r.name);
10394 mServicesByIntent.remove(r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010395 r.totalRestartCount = 0;
10396 unscheduleServiceRestartLocked(r);
10397
10398 // Also make sure it is not on the pending list.
10399 int N = mPendingServices.size();
10400 for (int i=0; i<N; i++) {
10401 if (mPendingServices.get(i) == r) {
10402 mPendingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010403 if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010404 i--;
10405 N--;
10406 }
10407 }
10408
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010409 r.cancelNotification();
10410 r.isForeground = false;
10411 r.foregroundId = 0;
10412 r.foregroundNoti = null;
10413
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010414 // Clear start entries.
Dianne Hackborn39792d22010-08-19 18:01:52 -070010415 r.clearDeliveredStartsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010416 r.pendingStarts.clear();
10417
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010418 if (r.app != null) {
10419 synchronized (r.stats.getBatteryStats()) {
10420 r.stats.stopLaunchedLocked();
10421 }
10422 r.app.services.remove(r);
10423 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010424 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010425 bumpServiceExecutingLocked(r, "stop");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010426 mStoppingServices.add(r);
10427 updateOomAdjLocked(r.app);
10428 r.app.thread.scheduleStopService(r);
10429 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010430 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010431 + r.shortName, e);
10432 serviceDoneExecutingLocked(r, true);
10433 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010434 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010435 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010436 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010437 TAG, "Removed service that has no process: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010438 }
10439 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010440 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010441 TAG, "Removed service that is not running: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010442 }
Vairavan Srinivasana207ce22010-12-23 13:51:48 -080010443
10444 if (r.bindings.size() > 0) {
10445 r.bindings.clear();
10446 }
10447
10448 if (r.restarter instanceof ServiceRestarter) {
10449 ((ServiceRestarter)r.restarter).setService(null);
10450 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010451 }
10452
10453 ComponentName startServiceLocked(IApplicationThread caller,
10454 Intent service, String resolvedType,
10455 int callingPid, int callingUid) {
10456 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010457 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010458 + " type=" + resolvedType + " args=" + service.getExtras());
10459
10460 if (caller != null) {
10461 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10462 if (callerApp == null) {
10463 throw new SecurityException(
10464 "Unable to find app for caller " + caller
10465 + " (pid=" + Binder.getCallingPid()
10466 + ") when starting service " + service);
10467 }
10468 }
10469
10470 ServiceLookupResult res =
10471 retrieveServiceLocked(service, resolvedType,
10472 callingPid, callingUid);
10473 if (res == null) {
10474 return null;
10475 }
10476 if (res.record == null) {
10477 return new ComponentName("!", res.permission != null
10478 ? res.permission : "private to package");
10479 }
10480 ServiceRecord r = res.record;
Dianne Hackborn39792d22010-08-19 18:01:52 -070010481 int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
10482 callingUid, r.packageName, service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010483 if (unscheduleServiceRestartLocked(r)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010484 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010485 }
10486 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010487 r.callStart = false;
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010488 r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
Dianne Hackborn39792d22010-08-19 18:01:52 -070010489 service, targetPermissionUid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010490 r.lastActivity = SystemClock.uptimeMillis();
10491 synchronized (r.stats.getBatteryStats()) {
10492 r.stats.startRunningLocked();
10493 }
10494 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
10495 return new ComponentName("!", "Service process is bad");
10496 }
10497 return r.name;
10498 }
10499 }
10500
10501 public ComponentName startService(IApplicationThread caller, Intent service,
10502 String resolvedType) {
10503 // Refuse possible leaked file descriptors
10504 if (service != null && service.hasFileDescriptors() == true) {
10505 throw new IllegalArgumentException("File descriptors passed in Intent");
10506 }
10507
10508 synchronized(this) {
10509 final int callingPid = Binder.getCallingPid();
10510 final int callingUid = Binder.getCallingUid();
10511 final long origId = Binder.clearCallingIdentity();
10512 ComponentName res = startServiceLocked(caller, service,
10513 resolvedType, callingPid, callingUid);
10514 Binder.restoreCallingIdentity(origId);
10515 return res;
10516 }
10517 }
10518
10519 ComponentName startServiceInPackage(int uid,
10520 Intent service, String resolvedType) {
10521 synchronized(this) {
10522 final long origId = Binder.clearCallingIdentity();
10523 ComponentName res = startServiceLocked(null, service,
10524 resolvedType, -1, uid);
10525 Binder.restoreCallingIdentity(origId);
10526 return res;
10527 }
10528 }
10529
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010530 private void stopServiceLocked(ServiceRecord service) {
10531 synchronized (service.stats.getBatteryStats()) {
10532 service.stats.stopRunningLocked();
10533 }
10534 service.startRequested = false;
10535 service.callStart = false;
10536 bringDownServiceLocked(service, false);
10537 }
10538
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010539 public int stopService(IApplicationThread caller, Intent service,
10540 String resolvedType) {
10541 // Refuse possible leaked file descriptors
10542 if (service != null && service.hasFileDescriptors() == true) {
10543 throw new IllegalArgumentException("File descriptors passed in Intent");
10544 }
10545
10546 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010547 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010548 + " type=" + resolvedType);
10549
10550 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10551 if (caller != null && callerApp == null) {
10552 throw new SecurityException(
10553 "Unable to find app for caller " + caller
10554 + " (pid=" + Binder.getCallingPid()
10555 + ") when stopping service " + service);
10556 }
10557
10558 // If this service is active, make sure it is stopped.
10559 ServiceLookupResult r = findServiceLocked(service, resolvedType);
10560 if (r != null) {
10561 if (r.record != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010562 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010563 try {
10564 stopServiceLocked(r.record);
10565 } finally {
10566 Binder.restoreCallingIdentity(origId);
10567 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010568 return 1;
10569 }
10570 return -1;
10571 }
10572 }
10573
10574 return 0;
10575 }
10576
10577 public IBinder peekService(Intent service, String resolvedType) {
10578 // Refuse possible leaked file descriptors
10579 if (service != null && service.hasFileDescriptors() == true) {
10580 throw new IllegalArgumentException("File descriptors passed in Intent");
10581 }
10582
10583 IBinder ret = null;
10584
10585 synchronized(this) {
10586 ServiceLookupResult r = findServiceLocked(service, resolvedType);
10587
10588 if (r != null) {
10589 // r.record is null if findServiceLocked() failed the caller permission check
10590 if (r.record == null) {
10591 throw new SecurityException(
10592 "Permission Denial: Accessing service " + r.record.name
10593 + " from pid=" + Binder.getCallingPid()
10594 + ", uid=" + Binder.getCallingUid()
10595 + " requires " + r.permission);
10596 }
10597 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
10598 if (ib != null) {
10599 ret = ib.binder;
10600 }
10601 }
10602 }
10603
10604 return ret;
10605 }
10606
10607 public boolean stopServiceToken(ComponentName className, IBinder token,
10608 int startId) {
10609 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010610 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010611 + " " + token + " startId=" + startId);
10612 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010613 if (r != null) {
10614 if (startId >= 0) {
10615 // Asked to only stop if done with all work. Note that
10616 // to avoid leaks, we will take this as dropping all
10617 // start items up to and including this one.
10618 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
10619 if (si != null) {
10620 while (r.deliveredStarts.size() > 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -070010621 ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
10622 cur.removeUriPermissionsLocked();
10623 if (cur == si) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010624 break;
10625 }
10626 }
10627 }
10628
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010629 if (r.getLastStartId() != startId) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010630 return false;
10631 }
10632
10633 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010634 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010635 + " is last, but have " + r.deliveredStarts.size()
10636 + " remaining args");
10637 }
10638 }
10639
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010640 synchronized (r.stats.getBatteryStats()) {
10641 r.stats.stopRunningLocked();
10642 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010643 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010644 }
10645 final long origId = Binder.clearCallingIdentity();
10646 bringDownServiceLocked(r, false);
10647 Binder.restoreCallingIdentity(origId);
10648 return true;
10649 }
10650 }
10651 return false;
10652 }
10653
10654 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010655 int id, Notification notification, boolean removeNotification) {
10656 final long origId = Binder.clearCallingIdentity();
10657 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010658 synchronized(this) {
10659 ServiceRecord r = findServiceLocked(className, token);
10660 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010661 if (id != 0) {
10662 if (notification == null) {
10663 throw new IllegalArgumentException("null notification");
10664 }
10665 if (r.foregroundId != id) {
10666 r.cancelNotification();
10667 r.foregroundId = id;
10668 }
10669 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
10670 r.foregroundNoti = notification;
10671 r.isForeground = true;
10672 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010673 if (r.app != null) {
10674 updateServiceForegroundLocked(r.app, true);
10675 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010676 } else {
10677 if (r.isForeground) {
10678 r.isForeground = false;
10679 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -070010680 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010681 updateServiceForegroundLocked(r.app, true);
10682 }
10683 }
10684 if (removeNotification) {
10685 r.cancelNotification();
10686 r.foregroundId = 0;
10687 r.foregroundNoti = null;
10688 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010689 }
10690 }
10691 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010692 } finally {
10693 Binder.restoreCallingIdentity(origId);
10694 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010695 }
10696
10697 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
10698 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -070010699 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010700 if (sr.isForeground) {
10701 anyForeground = true;
10702 break;
10703 }
10704 }
10705 if (anyForeground != proc.foregroundServices) {
10706 proc.foregroundServices = anyForeground;
10707 if (oomAdj) {
10708 updateOomAdjLocked();
10709 }
10710 }
10711 }
10712
10713 public int bindService(IApplicationThread caller, IBinder token,
10714 Intent service, String resolvedType,
10715 IServiceConnection connection, int flags) {
10716 // Refuse possible leaked file descriptors
10717 if (service != null && service.hasFileDescriptors() == true) {
10718 throw new IllegalArgumentException("File descriptors passed in Intent");
10719 }
10720
10721 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010722 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010723 + " type=" + resolvedType + " conn=" + connection.asBinder()
10724 + " flags=0x" + Integer.toHexString(flags));
10725 final ProcessRecord callerApp = getRecordForAppLocked(caller);
10726 if (callerApp == null) {
10727 throw new SecurityException(
10728 "Unable to find app for caller " + caller
10729 + " (pid=" + Binder.getCallingPid()
10730 + ") when binding service " + service);
10731 }
10732
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010733 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010734 if (token != null) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -070010735 activity = mMainStack.isInStackLocked(token);
10736 if (activity == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010737 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010738 return 0;
10739 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010740 }
10741
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010742 int clientLabel = 0;
10743 PendingIntent clientIntent = null;
10744
10745 if (callerApp.info.uid == Process.SYSTEM_UID) {
10746 // Hacky kind of thing -- allow system stuff to tell us
10747 // what they are, so we can report this elsewhere for
10748 // others to know why certain services are running.
10749 try {
10750 clientIntent = (PendingIntent)service.getParcelableExtra(
10751 Intent.EXTRA_CLIENT_INTENT);
10752 } catch (RuntimeException e) {
10753 }
10754 if (clientIntent != null) {
10755 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
10756 if (clientLabel != 0) {
10757 // There are no useful extras in the intent, trash them.
10758 // System code calling with this stuff just needs to know
10759 // this will happen.
10760 service = service.cloneFilter();
10761 }
10762 }
10763 }
10764
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010765 ServiceLookupResult res =
10766 retrieveServiceLocked(service, resolvedType,
10767 Binder.getCallingPid(), Binder.getCallingUid());
10768 if (res == null) {
10769 return 0;
10770 }
10771 if (res.record == null) {
10772 return -1;
10773 }
10774 ServiceRecord s = res.record;
10775
10776 final long origId = Binder.clearCallingIdentity();
10777
10778 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010779 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010780 + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010781 }
10782
10783 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
10784 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010785 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010786
10787 IBinder binder = connection.asBinder();
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010788 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
10789 if (clist == null) {
10790 clist = new ArrayList<ConnectionRecord>();
10791 s.connections.put(binder, clist);
10792 }
10793 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010794 b.connections.add(c);
10795 if (activity != null) {
10796 if (activity.connections == null) {
10797 activity.connections = new HashSet<ConnectionRecord>();
10798 }
10799 activity.connections.add(c);
10800 }
10801 b.client.connections.add(c);
Dianne Hackbornc68c9132011-07-29 01:25:18 -070010802 if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) {
10803 b.client.hasAboveClient = true;
10804 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010805 clist = mServiceConnections.get(binder);
10806 if (clist == null) {
10807 clist = new ArrayList<ConnectionRecord>();
10808 mServiceConnections.put(binder, clist);
10809 }
10810 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010811
10812 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
10813 s.lastActivity = SystemClock.uptimeMillis();
10814 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
10815 return 0;
10816 }
10817 }
10818
10819 if (s.app != null) {
10820 // This could have made the service more important.
10821 updateOomAdjLocked(s.app);
10822 }
10823
Joe Onorato8a9b2202010-02-26 18:56:32 -080010824 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010825 + ": received=" + b.intent.received
10826 + " apps=" + b.intent.apps.size()
10827 + " doRebind=" + b.intent.doRebind);
10828
10829 if (s.app != null && b.intent.received) {
10830 // Service is already running, so we can immediately
10831 // publish the connection.
10832 try {
10833 c.conn.connected(s.name, b.intent.binder);
10834 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010835 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010836 + " to connection " + c.conn.asBinder()
10837 + " (in " + c.binding.client.processName + ")", e);
10838 }
10839
10840 // If this is the first app connected back to this binding,
10841 // and the service had previously asked to be told when
10842 // rebound, then do so.
10843 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
10844 requestServiceBindingLocked(s, b.intent, true);
10845 }
10846 } else if (!b.intent.requested) {
10847 requestServiceBindingLocked(s, b.intent, false);
10848 }
10849
10850 Binder.restoreCallingIdentity(origId);
10851 }
10852
10853 return 1;
10854 }
10855
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070010856 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010857 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010858 IBinder binder = c.conn.asBinder();
10859 AppBindRecord b = c.binding;
10860 ServiceRecord s = b.service;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010861 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
10862 if (clist != null) {
10863 clist.remove(c);
10864 if (clist.size() == 0) {
10865 s.connections.remove(binder);
10866 }
10867 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010868 b.connections.remove(c);
10869 if (c.activity != null && c.activity != skipAct) {
10870 if (c.activity.connections != null) {
10871 c.activity.connections.remove(c);
10872 }
10873 }
10874 if (b.client != skipApp) {
10875 b.client.connections.remove(c);
Dianne Hackbornc68c9132011-07-29 01:25:18 -070010876 if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) {
10877 b.client.updateHasAboveClientLocked();
10878 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010879 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010880 clist = mServiceConnections.get(binder);
10881 if (clist != null) {
10882 clist.remove(c);
10883 if (clist.size() == 0) {
10884 mServiceConnections.remove(binder);
10885 }
10886 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010887
10888 if (b.connections.size() == 0) {
10889 b.intent.apps.remove(b.client);
10890 }
10891
Dianne Hackborn130b0d22011-07-26 22:07:48 -070010892 if (!c.serviceDead) {
10893 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
10894 + ": shouldUnbind=" + b.intent.hasBound);
10895 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
10896 && b.intent.hasBound) {
10897 try {
10898 bumpServiceExecutingLocked(s, "unbind");
10899 updateOomAdjLocked(s.app);
10900 b.intent.hasBound = false;
10901 // Assume the client doesn't want to know about a rebind;
10902 // we will deal with that later if it asks for one.
10903 b.intent.doRebind = false;
10904 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
10905 } catch (Exception e) {
10906 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
10907 serviceDoneExecutingLocked(s, true);
10908 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010909 }
Dianne Hackborn130b0d22011-07-26 22:07:48 -070010910
10911 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
10912 bringDownServiceLocked(s, false);
10913 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010914 }
10915 }
10916
10917 public boolean unbindService(IServiceConnection connection) {
10918 synchronized (this) {
10919 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010920 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010921 ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
10922 if (clist == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010923 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010924 + connection.asBinder());
10925 return false;
10926 }
10927
10928 final long origId = Binder.clearCallingIdentity();
10929
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010930 while (clist.size() > 0) {
10931 ConnectionRecord r = clist.get(0);
10932 removeConnectionLocked(r, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010933
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010934 if (r.binding.service.app != null) {
10935 // This could have made the service less important.
10936 updateOomAdjLocked(r.binding.service.app);
10937 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010938 }
10939
10940 Binder.restoreCallingIdentity(origId);
10941 }
10942
10943 return true;
10944 }
10945
10946 public void publishService(IBinder token, Intent intent, IBinder service) {
10947 // Refuse possible leaked file descriptors
10948 if (intent != null && intent.hasFileDescriptors() == true) {
10949 throw new IllegalArgumentException("File descriptors passed in Intent");
10950 }
10951
10952 synchronized(this) {
10953 if (!(token instanceof ServiceRecord)) {
10954 throw new IllegalArgumentException("Invalid service token");
10955 }
10956 ServiceRecord r = (ServiceRecord)token;
10957
10958 final long origId = Binder.clearCallingIdentity();
10959
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010960 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010961 + " " + intent + ": " + service);
10962 if (r != null) {
10963 Intent.FilterComparison filter
10964 = new Intent.FilterComparison(intent);
10965 IntentBindRecord b = r.bindings.get(filter);
10966 if (b != null && !b.received) {
10967 b.binder = service;
10968 b.requested = true;
10969 b.received = true;
10970 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010971 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010972 = r.connections.values().iterator();
10973 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010974 ArrayList<ConnectionRecord> clist = it.next();
10975 for (int i=0; i<clist.size(); i++) {
10976 ConnectionRecord c = clist.get(i);
10977 if (!filter.equals(c.binding.intent.intent)) {
10978 if (DEBUG_SERVICE) Slog.v(
10979 TAG, "Not publishing to: " + c);
10980 if (DEBUG_SERVICE) Slog.v(
10981 TAG, "Bound intent: " + c.binding.intent.intent);
10982 if (DEBUG_SERVICE) Slog.v(
10983 TAG, "Published intent: " + intent);
10984 continue;
10985 }
10986 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
10987 try {
10988 c.conn.connected(r.name, service);
10989 } catch (Exception e) {
10990 Slog.w(TAG, "Failure sending service " + r.name +
10991 " to connection " + c.conn.asBinder() +
10992 " (in " + c.binding.client.processName + ")", e);
10993 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010994 }
10995 }
10996 }
10997 }
10998
10999 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
11000
11001 Binder.restoreCallingIdentity(origId);
11002 }
11003 }
11004 }
11005
11006 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
11007 // Refuse possible leaked file descriptors
11008 if (intent != null && intent.hasFileDescriptors() == true) {
11009 throw new IllegalArgumentException("File descriptors passed in Intent");
11010 }
11011
11012 synchronized(this) {
11013 if (!(token instanceof ServiceRecord)) {
11014 throw new IllegalArgumentException("Invalid service token");
11015 }
11016 ServiceRecord r = (ServiceRecord)token;
11017
11018 final long origId = Binder.clearCallingIdentity();
11019
11020 if (r != null) {
11021 Intent.FilterComparison filter
11022 = new Intent.FilterComparison(intent);
11023 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011024 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011025 + " at " + b + ": apps="
11026 + (b != null ? b.apps.size() : 0));
Per Edelberg78f9fff2010-08-30 20:01:35 +020011027
11028 boolean inStopping = mStoppingServices.contains(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011029 if (b != null) {
Per Edelberg78f9fff2010-08-30 20:01:35 +020011030 if (b.apps.size() > 0 && !inStopping) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011031 // Applications have already bound since the last
11032 // unbind, so just rebind right here.
11033 requestServiceBindingLocked(r, b, true);
11034 } else {
11035 // Note to tell the service the next time there is
11036 // a new client.
11037 b.doRebind = true;
11038 }
11039 }
11040
Per Edelberg78f9fff2010-08-30 20:01:35 +020011041 serviceDoneExecutingLocked(r, inStopping);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011042
11043 Binder.restoreCallingIdentity(origId);
11044 }
11045 }
11046 }
11047
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011048 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011049 synchronized(this) {
11050 if (!(token instanceof ServiceRecord)) {
11051 throw new IllegalArgumentException("Invalid service token");
11052 }
11053 ServiceRecord r = (ServiceRecord)token;
11054 boolean inStopping = mStoppingServices.contains(token);
11055 if (r != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011056 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011057 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011058 + " with incorrect token: given " + token
11059 + ", expected " + r);
11060 return;
11061 }
11062
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011063 if (type == 1) {
11064 // This is a call from a service start... take care of
11065 // book-keeping.
11066 r.callStart = true;
11067 switch (res) {
11068 case Service.START_STICKY_COMPATIBILITY:
11069 case Service.START_STICKY: {
11070 // We are done with the associated start arguments.
11071 r.findDeliveredStart(startId, true);
11072 // Don't stop if killed.
11073 r.stopIfKilled = false;
11074 break;
11075 }
11076 case Service.START_NOT_STICKY: {
11077 // We are done with the associated start arguments.
11078 r.findDeliveredStart(startId, true);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070011079 if (r.getLastStartId() == startId) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011080 // There is no more work, and this service
11081 // doesn't want to hang around if killed.
11082 r.stopIfKilled = true;
11083 }
11084 break;
11085 }
11086 case Service.START_REDELIVER_INTENT: {
11087 // We'll keep this item until they explicitly
11088 // call stop for it, but keep track of the fact
11089 // that it was delivered.
11090 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
11091 if (si != null) {
11092 si.deliveryCount = 0;
11093 si.doneExecutingCount++;
11094 // Don't stop if killed.
11095 r.stopIfKilled = true;
11096 }
11097 break;
11098 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070011099 case Service.START_TASK_REMOVED_COMPLETE: {
11100 // Special processing for onTaskRemoved(). Don't
11101 // impact normal onStartCommand() processing.
11102 r.findDeliveredStart(startId, true);
11103 break;
11104 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011105 default:
11106 throw new IllegalArgumentException(
11107 "Unknown service start result: " + res);
11108 }
11109 if (res == Service.START_STICKY_COMPATIBILITY) {
11110 r.callStart = false;
11111 }
11112 }
11113
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011114 final long origId = Binder.clearCallingIdentity();
11115 serviceDoneExecutingLocked(r, inStopping);
11116 Binder.restoreCallingIdentity(origId);
11117 } else {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011118 Slog.w(TAG, "Done executing unknown service from pid "
11119 + Binder.getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011120 }
11121 }
11122 }
11123
11124 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011125 if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
11126 + ": nesting=" + r.executeNesting
11127 + ", inStopping=" + inStopping + ", app=" + r.app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070011128 else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011129 r.executeNesting--;
11130 if (r.executeNesting <= 0 && r.app != null) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070011131 if (DEBUG_SERVICE) Slog.v(TAG,
11132 "Nesting at 0 of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011133 r.app.executingServices.remove(r);
11134 if (r.app.executingServices.size() == 0) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070011135 if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,
11136 "No more executingServices of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011137 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
11138 }
11139 if (inStopping) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070011140 if (DEBUG_SERVICE) Slog.v(TAG,
11141 "doneExecuting remove stopping " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011142 mStoppingServices.remove(r);
Mattias Petersson3996b412010-10-27 09:32:51 +020011143 r.bindings.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011144 }
11145 updateOomAdjLocked(r.app);
11146 }
11147 }
11148
11149 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011150 String anrMessage = null;
11151
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011152 synchronized(this) {
11153 if (proc.executingServices.size() == 0 || proc.thread == null) {
11154 return;
11155 }
11156 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
11157 Iterator<ServiceRecord> it = proc.executingServices.iterator();
11158 ServiceRecord timeout = null;
11159 long nextTime = 0;
11160 while (it.hasNext()) {
11161 ServiceRecord sr = it.next();
11162 if (sr.executingStart < maxTime) {
11163 timeout = sr;
11164 break;
11165 }
11166 if (sr.executingStart > nextTime) {
11167 nextTime = sr.executingStart;
11168 }
11169 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011170 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011171 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011172 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011173 } else {
11174 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
11175 msg.obj = proc;
11176 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
11177 }
11178 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011179
11180 if (anrMessage != null) {
11181 appNotResponding(proc, null, null, anrMessage);
11182 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011183 }
11184
11185 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070011186 // BACKUP AND RESTORE
11187 // =========================================================
11188
11189 // Cause the target app to be launched if necessary and its backup agent
11190 // instantiated. The backup agent will invoke backupAgentCreated() on the
11191 // activity manager to announce its creation.
11192 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011193 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070011194 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
11195
11196 synchronized(this) {
11197 // !!! TODO: currently no check here that we're already bound
11198 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
11199 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
11200 synchronized (stats) {
11201 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
11202 }
11203
Dianne Hackborne7f97212011-02-24 14:40:20 -080011204 // Backup agent is now in use, its package can't be stopped.
11205 try {
11206 AppGlobals.getPackageManager().setPackageStoppedState(
11207 app.packageName, false);
11208 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -080011209 } catch (IllegalArgumentException e) {
11210 Slog.w(TAG, "Failed trying to unstop package "
11211 + app.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -080011212 }
11213
Christopher Tate181fafa2009-05-14 11:12:14 -070011214 BackupRecord r = new BackupRecord(ss, app, backupMode);
Christopher Tate4a627c72011-04-01 14:43:32 -070011215 ComponentName hostingName = (backupMode == IApplicationThread.BACKUP_MODE_INCREMENTAL)
11216 ? new ComponentName(app.packageName, app.backupAgentName)
11217 : new ComponentName("android", "FullBackupAgent");
Christopher Tate181fafa2009-05-14 11:12:14 -070011218 // startProcessLocked() returns existing proc's record if it's already running
11219 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011220 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070011221 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011222 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070011223 return false;
11224 }
11225
11226 r.app = proc;
11227 mBackupTarget = r;
11228 mBackupAppName = app.packageName;
11229
Christopher Tate6fa95972009-06-05 18:43:55 -070011230 // Try not to kill the process during backup
11231 updateOomAdjLocked(proc);
11232
Christopher Tate181fafa2009-05-14 11:12:14 -070011233 // If the process is already attached, schedule the creation of the backup agent now.
11234 // If it is not yet live, this will be done when it attaches to the framework.
11235 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011236 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070011237 try {
Dianne Hackborne2515ee2011-04-27 18:52:56 -040011238 proc.thread.scheduleCreateBackupAgent(app,
11239 compatibilityInfoForPackageLocked(app), backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070011240 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070011241 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070011242 }
11243 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011244 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070011245 }
11246 // Invariants: at this point, the target app process exists and the application
11247 // is either already running or in the process of coming up. mBackupTarget and
11248 // mBackupAppName describe the app, so that when it binds back to the AM we
11249 // know that it's scheduled for a backup-agent operation.
11250 }
11251
11252 return true;
11253 }
11254
11255 // A backup agent has just come up
11256 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011257 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070011258 + " = " + agent);
11259
11260 synchronized(this) {
11261 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011262 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070011263 return;
11264 }
Dianne Hackborn06740692010-09-22 22:46:21 -070011265 }
Christopher Tate181fafa2009-05-14 11:12:14 -070011266
Dianne Hackborn06740692010-09-22 22:46:21 -070011267 long oldIdent = Binder.clearCallingIdentity();
11268 try {
11269 IBackupManager bm = IBackupManager.Stub.asInterface(
11270 ServiceManager.getService(Context.BACKUP_SERVICE));
11271 bm.agentConnected(agentPackageName, agent);
11272 } catch (RemoteException e) {
11273 // can't happen; the backup manager service is local
11274 } catch (Exception e) {
11275 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
11276 e.printStackTrace();
11277 } finally {
11278 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070011279 }
11280 }
11281
11282 // done with this agent
11283 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011284 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070011285 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011286 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070011287 return;
11288 }
Christopher Tate181fafa2009-05-14 11:12:14 -070011289
11290 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070011291 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011292 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070011293 return;
11294 }
11295
Christopher Tate181fafa2009-05-14 11:12:14 -070011296 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011297 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070011298 return;
11299 }
11300
Christopher Tate6fa95972009-06-05 18:43:55 -070011301 ProcessRecord proc = mBackupTarget.app;
11302 mBackupTarget = null;
11303 mBackupAppName = null;
11304
11305 // Not backing this app up any more; reset its OOM adjustment
11306 updateOomAdjLocked(proc);
11307
Christopher Tatec7b31e32009-06-10 15:49:30 -070011308 // If the app crashed during backup, 'thread' will be null here
11309 if (proc.thread != null) {
11310 try {
Dianne Hackborne2515ee2011-04-27 18:52:56 -040011311 proc.thread.scheduleDestroyBackupAgent(appInfo,
11312 compatibilityInfoForPackageLocked(appInfo));
Christopher Tatec7b31e32009-06-10 15:49:30 -070011313 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011314 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070011315 e.printStackTrace();
11316 }
Christopher Tate181fafa2009-05-14 11:12:14 -070011317 }
Christopher Tate181fafa2009-05-14 11:12:14 -070011318 }
11319 }
11320 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011321 // BROADCASTS
11322 // =========================================================
11323
Josh Bartel7f208742010-02-25 11:01:44 -060011324 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011325 List cur) {
11326 final ContentResolver resolver = mContext.getContentResolver();
11327 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
11328 if (list == null) {
11329 return cur;
11330 }
11331 int N = list.size();
11332 for (int i=0; i<N; i++) {
11333 Intent intent = list.get(i);
11334 if (filter.match(resolver, intent, true, TAG) >= 0) {
11335 if (cur == null) {
11336 cur = new ArrayList<Intent>();
11337 }
11338 cur.add(intent);
11339 }
11340 }
11341 return cur;
11342 }
11343
11344 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011345 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011346 + mBroadcastsScheduled);
11347
11348 if (mBroadcastsScheduled) {
11349 return;
11350 }
11351 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
11352 mBroadcastsScheduled = true;
11353 }
11354
Dianne Hackborn6c418d52011-06-29 14:05:33 -070011355 public Intent registerReceiver(IApplicationThread caller, String callerPackage,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011356 IIntentReceiver receiver, IntentFilter filter, String permission) {
11357 synchronized(this) {
11358 ProcessRecord callerApp = null;
11359 if (caller != null) {
11360 callerApp = getRecordForAppLocked(caller);
11361 if (callerApp == null) {
11362 throw new SecurityException(
11363 "Unable to find app for caller " + caller
11364 + " (pid=" + Binder.getCallingPid()
11365 + ") when registering receiver " + receiver);
11366 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -070011367 if (callerApp.info.uid != Process.SYSTEM_UID &&
11368 !callerApp.pkgList.contains(callerPackage)) {
11369 throw new SecurityException("Given caller package " + callerPackage
11370 + " is not running in process " + callerApp);
11371 }
11372 } else {
11373 callerPackage = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011374 }
11375
11376 List allSticky = null;
11377
11378 // Look for any matching sticky broadcasts...
11379 Iterator actions = filter.actionsIterator();
11380 if (actions != null) {
11381 while (actions.hasNext()) {
11382 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -060011383 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011384 }
11385 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060011386 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011387 }
11388
11389 // The first sticky in the list is returned directly back to
11390 // the client.
11391 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
11392
Joe Onorato8a9b2202010-02-26 18:56:32 -080011393 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011394 + ": " + sticky);
11395
11396 if (receiver == null) {
11397 return sticky;
11398 }
11399
11400 ReceiverList rl
11401 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
11402 if (rl == null) {
11403 rl = new ReceiverList(this, callerApp,
11404 Binder.getCallingPid(),
11405 Binder.getCallingUid(), receiver);
11406 if (rl.app != null) {
11407 rl.app.receivers.add(rl);
11408 } else {
11409 try {
11410 receiver.asBinder().linkToDeath(rl, 0);
11411 } catch (RemoteException e) {
11412 return sticky;
11413 }
11414 rl.linkedToDeath = true;
11415 }
11416 mRegisteredReceivers.put(receiver.asBinder(), rl);
11417 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -070011418 BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage, permission);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011419 rl.add(bf);
11420 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011421 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011422 }
11423 mReceiverResolver.addFilter(bf);
11424
11425 // Enqueue broadcasts for all existing stickies that match
11426 // this filter.
11427 if (allSticky != null) {
11428 ArrayList receivers = new ArrayList();
11429 receivers.add(bf);
11430
11431 int N = allSticky.size();
11432 for (int i=0; i<N; i++) {
11433 Intent intent = (Intent)allSticky.get(i);
11434 BroadcastRecord r = new BroadcastRecord(intent, null,
11435 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011436 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011437 if (mParallelBroadcasts.size() == 0) {
11438 scheduleBroadcastsLocked();
11439 }
11440 mParallelBroadcasts.add(r);
11441 }
11442 }
11443
11444 return sticky;
11445 }
11446 }
11447
11448 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011449 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011450
11451 boolean doNext = false;
11452
11453 synchronized(this) {
11454 ReceiverList rl
11455 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
11456 if (rl != null) {
11457 if (rl.curBroadcast != null) {
11458 BroadcastRecord r = rl.curBroadcast;
11459 doNext = finishReceiverLocked(
11460 receiver.asBinder(), r.resultCode, r.resultData,
11461 r.resultExtras, r.resultAbort, true);
11462 }
11463
11464 if (rl.app != null) {
11465 rl.app.receivers.remove(rl);
11466 }
11467 removeReceiverLocked(rl);
11468 if (rl.linkedToDeath) {
11469 rl.linkedToDeath = false;
11470 rl.receiver.asBinder().unlinkToDeath(rl, 0);
11471 }
11472 }
11473 }
11474
11475 if (!doNext) {
11476 return;
11477 }
11478
11479 final long origId = Binder.clearCallingIdentity();
11480 processNextBroadcast(false);
11481 trimApplications();
11482 Binder.restoreCallingIdentity(origId);
11483 }
11484
11485 void removeReceiverLocked(ReceiverList rl) {
11486 mRegisteredReceivers.remove(rl.receiver.asBinder());
11487 int N = rl.size();
11488 for (int i=0; i<N; i++) {
11489 mReceiverResolver.removeFilter(rl.get(i));
11490 }
11491 }
11492
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070011493 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
11494 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
11495 ProcessRecord r = mLruProcesses.get(i);
11496 if (r.thread != null) {
11497 try {
11498 r.thread.dispatchPackageBroadcast(cmd, packages);
11499 } catch (RemoteException ex) {
11500 }
11501 }
11502 }
11503 }
11504
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011505 private final int broadcastIntentLocked(ProcessRecord callerApp,
11506 String callerPackage, Intent intent, String resolvedType,
11507 IIntentReceiver resultTo, int resultCode, String resultData,
11508 Bundle map, String requiredPermission,
11509 boolean ordered, boolean sticky, int callingPid, int callingUid) {
11510 intent = new Intent(intent);
11511
Dianne Hackborne7f97212011-02-24 14:40:20 -080011512 // By default broadcasts do not go to stopped apps.
11513 intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
11514
Joe Onorato8a9b2202010-02-26 18:56:32 -080011515 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011516 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
11517 + " ordered=" + ordered);
11518 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011519 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011520 }
11521
11522 // Handle special intents: if this broadcast is from the package
11523 // manager about a package being removed, we need to remove all of
11524 // its activities from the history stack.
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011525 final boolean uidRemoved = Intent.ACTION_UID_REMOVED.equals(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011526 intent.getAction());
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011527 if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
11528 || Intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080011529 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011530 || uidRemoved) {
11531 if (checkComponentPermission(
11532 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080011533 callingPid, callingUid, -1, true)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011534 == PackageManager.PERMISSION_GRANTED) {
11535 if (uidRemoved) {
11536 final Bundle intentExtras = intent.getExtras();
11537 final int uid = intentExtras != null
11538 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
11539 if (uid >= 0) {
11540 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
11541 synchronized (bs) {
11542 bs.removeUidStatsLocked(uid);
11543 }
11544 }
11545 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011546 // If resources are unvailble just force stop all
11547 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080011548 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011549 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
11550 if (list != null && (list.length > 0)) {
11551 for (String pkg : list) {
Christopher Tate3dacd842011-08-19 14:56:15 -070011552 forceStopPackageLocked(pkg, -1, false, true, true, false);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011553 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070011554 sendPackageBroadcastLocked(
11555 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011556 }
11557 } else {
11558 Uri data = intent.getData();
11559 String ssp;
11560 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
11561 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
11562 forceStopPackageLocked(ssp,
Christopher Tate3dacd842011-08-19 14:56:15 -070011563 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true, false);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070011564 }
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011565 if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070011566 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
11567 new String[] {ssp});
11568 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011569 }
11570 }
11571 }
11572 } else {
11573 String msg = "Permission Denial: " + intent.getAction()
11574 + " broadcast from " + callerPackage + " (pid=" + callingPid
11575 + ", uid=" + callingUid + ")"
11576 + " requires "
11577 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011578 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011579 throw new SecurityException(msg);
11580 }
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011581
11582 // Special case for adding a package: by default turn on compatibility
11583 // mode.
11584 } else if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())) {
Dianne Hackborn8ea5e1d2011-05-27 16:45:31 -070011585 Uri data = intent.getData();
11586 String ssp;
11587 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
11588 mCompatModePackages.handlePackageAddedLocked(ssp,
11589 intent.getBooleanExtra(Intent.EXTRA_REPLACING, false));
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011590 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011591 }
11592
11593 /*
11594 * If this is the time zone changed action, queue up a message that will reset the timezone
11595 * of all currently running processes. This message will get queued up before the broadcast
11596 * happens.
11597 */
11598 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
11599 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
11600 }
11601
Robert Greenwalt03595d02010-11-02 14:08:23 -070011602 if (intent.ACTION_CLEAR_DNS_CACHE.equals(intent.getAction())) {
11603 mHandler.sendEmptyMessage(CLEAR_DNS_CACHE);
11604 }
11605
Robert Greenwalt434203a2010-10-11 16:00:27 -070011606 if (Proxy.PROXY_CHANGE_ACTION.equals(intent.getAction())) {
11607 ProxyProperties proxy = intent.getParcelableExtra("proxy");
11608 mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY, proxy));
11609 }
11610
Dianne Hackborn854060af2009-07-09 18:14:31 -070011611 /*
11612 * Prevent non-system code (defined here to be non-persistent
11613 * processes) from sending protected broadcasts.
11614 */
11615 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
11616 || callingUid == Process.SHELL_UID || callingUid == 0) {
11617 // Always okay.
11618 } else if (callerApp == null || !callerApp.persistent) {
11619 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011620 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -070011621 intent.getAction())) {
11622 String msg = "Permission Denial: not allowed to send broadcast "
11623 + intent.getAction() + " from pid="
11624 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011625 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070011626 throw new SecurityException(msg);
11627 }
11628 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011629 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070011630 return BROADCAST_SUCCESS;
11631 }
11632 }
11633
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011634 // Add to the sticky list if requested.
11635 if (sticky) {
11636 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
11637 callingPid, callingUid)
11638 != PackageManager.PERMISSION_GRANTED) {
11639 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
11640 + callingPid + ", uid=" + callingUid
11641 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011642 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011643 throw new SecurityException(msg);
11644 }
11645 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011646 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011647 + " and enforce permission " + requiredPermission);
11648 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
11649 }
11650 if (intent.getComponent() != null) {
11651 throw new SecurityException(
11652 "Sticky broadcasts can't target a specific component");
11653 }
11654 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
11655 if (list == null) {
11656 list = new ArrayList<Intent>();
11657 mStickyBroadcasts.put(intent.getAction(), list);
11658 }
11659 int N = list.size();
11660 int i;
11661 for (i=0; i<N; i++) {
11662 if (intent.filterEquals(list.get(i))) {
11663 // This sticky already exists, replace it.
11664 list.set(i, new Intent(intent));
11665 break;
11666 }
11667 }
11668 if (i >= N) {
11669 list.add(new Intent(intent));
11670 }
11671 }
11672
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011673 // Figure out who all will receive this broadcast.
11674 List receivers = null;
11675 List<BroadcastFilter> registeredReceivers = null;
11676 try {
11677 if (intent.getComponent() != null) {
11678 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011679 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070011680 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011681 if (ai != null) {
11682 receivers = new ArrayList();
11683 ResolveInfo ri = new ResolveInfo();
11684 ri.activityInfo = ai;
11685 receivers.add(ri);
11686 }
11687 } else {
11688 // Need to resolve the intent to interested receivers...
11689 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
11690 == 0) {
11691 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011692 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070011693 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011694 }
Mihai Preda074edef2009-05-18 17:13:31 +020011695 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011696 }
11697 } catch (RemoteException ex) {
11698 // pm is in same process, this will never happen.
11699 }
11700
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011701 final boolean replacePending =
11702 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
11703
Joe Onorato8a9b2202010-02-26 18:56:32 -080011704 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011705 + " replacePending=" + replacePending);
11706
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011707 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
11708 if (!ordered && NR > 0) {
11709 // If we are not serializing this broadcast, then send the
11710 // registered receivers separately so they don't wait for the
11711 // components to be launched.
11712 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
11713 callerPackage, callingPid, callingUid, requiredPermission,
11714 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011715 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011716 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011717 TAG, "Enqueueing parallel broadcast " + r
11718 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011719 boolean replaced = false;
11720 if (replacePending) {
11721 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
11722 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011723 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011724 "***** DROPPING PARALLEL: " + intent);
11725 mParallelBroadcasts.set(i, r);
11726 replaced = true;
11727 break;
11728 }
11729 }
11730 }
11731 if (!replaced) {
11732 mParallelBroadcasts.add(r);
11733 scheduleBroadcastsLocked();
11734 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011735 registeredReceivers = null;
11736 NR = 0;
11737 }
11738
11739 // Merge into one list.
11740 int ir = 0;
11741 if (receivers != null) {
11742 // A special case for PACKAGE_ADDED: do not allow the package
11743 // being added to see this broadcast. This prevents them from
11744 // using this as a back door to get run as soon as they are
11745 // installed. Maybe in the future we want to have a special install
11746 // broadcast or such for apps, but we'd like to deliberately make
11747 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011748 String skipPackages[] = null;
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011749 if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
11750 || Intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
11751 || Intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011752 Uri data = intent.getData();
11753 if (data != null) {
11754 String pkgName = data.getSchemeSpecificPart();
11755 if (pkgName != null) {
11756 skipPackages = new String[] { pkgName };
11757 }
11758 }
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070011759 } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011760 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070011761 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080011762 if (skipPackages != null && (skipPackages.length > 0)) {
11763 for (String skipPackage : skipPackages) {
11764 if (skipPackage != null) {
11765 int NT = receivers.size();
11766 for (int it=0; it<NT; it++) {
11767 ResolveInfo curt = (ResolveInfo)receivers.get(it);
11768 if (curt.activityInfo.packageName.equals(skipPackage)) {
11769 receivers.remove(it);
11770 it--;
11771 NT--;
11772 }
11773 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011774 }
11775 }
11776 }
11777
11778 int NT = receivers != null ? receivers.size() : 0;
11779 int it = 0;
11780 ResolveInfo curt = null;
11781 BroadcastFilter curr = null;
11782 while (it < NT && ir < NR) {
11783 if (curt == null) {
11784 curt = (ResolveInfo)receivers.get(it);
11785 }
11786 if (curr == null) {
11787 curr = registeredReceivers.get(ir);
11788 }
11789 if (curr.getPriority() >= curt.priority) {
11790 // Insert this broadcast record into the final list.
11791 receivers.add(it, curr);
11792 ir++;
11793 curr = null;
11794 it++;
11795 NT++;
11796 } else {
11797 // Skip to the next ResolveInfo in the final list.
11798 it++;
11799 curt = null;
11800 }
11801 }
11802 }
11803 while (ir < NR) {
11804 if (receivers == null) {
11805 receivers = new ArrayList();
11806 }
11807 receivers.add(registeredReceivers.get(ir));
11808 ir++;
11809 }
11810
11811 if ((receivers != null && receivers.size() > 0)
11812 || resultTo != null) {
11813 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
11814 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080011815 receivers, resultTo, resultCode, resultData, map, ordered,
11816 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011817 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011818 TAG, "Enqueueing ordered broadcast " + r
11819 + ": prev had " + mOrderedBroadcasts.size());
11820 if (DEBUG_BROADCAST) {
11821 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011822 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011823 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011824 boolean replaced = false;
11825 if (replacePending) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011826 for (int i=mOrderedBroadcasts.size()-1; i>0; i--) {
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011827 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011828 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080011829 "***** DROPPING ORDERED: " + intent);
11830 mOrderedBroadcasts.set(i, r);
11831 replaced = true;
11832 break;
11833 }
11834 }
11835 }
11836 if (!replaced) {
11837 mOrderedBroadcasts.add(r);
11838 scheduleBroadcastsLocked();
11839 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011840 }
11841
11842 return BROADCAST_SUCCESS;
11843 }
11844
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011845 final Intent verifyBroadcastLocked(Intent intent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011846 // Refuse possible leaked file descriptors
11847 if (intent != null && intent.hasFileDescriptors() == true) {
11848 throw new IllegalArgumentException("File descriptors passed in Intent");
11849 }
11850
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011851 int flags = intent.getFlags();
11852
11853 if (!mProcessesReady) {
11854 // if the caller really truly claims to know what they're doing, go
11855 // ahead and allow the broadcast without launching any receivers
11856 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
11857 intent = new Intent(intent);
11858 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
11859 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
11860 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
11861 + " before boot completion");
11862 throw new IllegalStateException("Cannot broadcast before boot completed");
11863 }
11864 }
11865
11866 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
11867 throw new IllegalArgumentException(
11868 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
11869 }
11870
11871 return intent;
11872 }
11873
11874 public final int broadcastIntent(IApplicationThread caller,
11875 Intent intent, String resolvedType, IIntentReceiver resultTo,
11876 int resultCode, String resultData, Bundle map,
11877 String requiredPermission, boolean serialized, boolean sticky) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011878 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011879 intent = verifyBroadcastLocked(intent);
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011880
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011881 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11882 final int callingPid = Binder.getCallingPid();
11883 final int callingUid = Binder.getCallingUid();
11884 final long origId = Binder.clearCallingIdentity();
11885 int res = broadcastIntentLocked(callerApp,
11886 callerApp != null ? callerApp.info.packageName : null,
11887 intent, resolvedType, resultTo,
11888 resultCode, resultData, map, requiredPermission, serialized,
11889 sticky, callingPid, callingUid);
11890 Binder.restoreCallingIdentity(origId);
11891 return res;
11892 }
11893 }
11894
11895 int broadcastIntentInPackage(String packageName, int uid,
11896 Intent intent, String resolvedType, IIntentReceiver resultTo,
11897 int resultCode, String resultData, Bundle map,
11898 String requiredPermission, boolean serialized, boolean sticky) {
11899 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070011900 intent = verifyBroadcastLocked(intent);
11901
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011902 final long origId = Binder.clearCallingIdentity();
11903 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
11904 resultTo, resultCode, resultData, map, requiredPermission,
11905 serialized, sticky, -1, uid);
11906 Binder.restoreCallingIdentity(origId);
11907 return res;
11908 }
11909 }
11910
11911 public final void unbroadcastIntent(IApplicationThread caller,
11912 Intent intent) {
11913 // Refuse possible leaked file descriptors
11914 if (intent != null && intent.hasFileDescriptors() == true) {
11915 throw new IllegalArgumentException("File descriptors passed in Intent");
11916 }
11917
11918 synchronized(this) {
11919 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
11920 != PackageManager.PERMISSION_GRANTED) {
11921 String msg = "Permission Denial: unbroadcastIntent() from pid="
11922 + Binder.getCallingPid()
11923 + ", uid=" + Binder.getCallingUid()
11924 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011925 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011926 throw new SecurityException(msg);
11927 }
11928 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
11929 if (list != null) {
11930 int N = list.size();
11931 int i;
11932 for (i=0; i<N; i++) {
11933 if (intent.filterEquals(list.get(i))) {
11934 list.remove(i);
11935 break;
11936 }
11937 }
11938 }
11939 }
11940 }
11941
11942 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
11943 String resultData, Bundle resultExtras, boolean resultAbort,
11944 boolean explicit) {
11945 if (mOrderedBroadcasts.size() == 0) {
11946 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011947 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011948 }
11949 return false;
11950 }
11951 BroadcastRecord r = mOrderedBroadcasts.get(0);
11952 if (r.receiver == null) {
11953 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011954 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011955 }
11956 return false;
11957 }
11958 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011959 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011960 return false;
11961 }
11962 int state = r.state;
Dianne Hackbornce86ba82011-07-13 19:33:41 -070011963 r.state = BroadcastRecord.IDLE;
11964 if (state == BroadcastRecord.IDLE) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011965 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011966 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011967 }
11968 }
11969 r.receiver = null;
11970 r.intent.setComponent(null);
11971 if (r.curApp != null) {
11972 r.curApp.curReceiver = null;
11973 }
11974 if (r.curFilter != null) {
11975 r.curFilter.receiverList.curBroadcast = null;
11976 }
11977 r.curFilter = null;
11978 r.curApp = null;
11979 r.curComponent = null;
11980 r.curReceiver = null;
11981 mPendingBroadcast = null;
11982
11983 r.resultCode = resultCode;
11984 r.resultData = resultData;
11985 r.resultExtras = resultExtras;
11986 r.resultAbort = resultAbort;
11987
11988 // We will process the next receiver right now if this is finishing
11989 // an app receiver (which is always asynchronous) or after we have
11990 // come back from calling a receiver.
11991 return state == BroadcastRecord.APP_RECEIVE
11992 || state == BroadcastRecord.CALL_DONE_RECEIVE;
11993 }
11994
11995 public void finishReceiver(IBinder who, int resultCode, String resultData,
11996 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011997 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011998
11999 // Refuse possible leaked file descriptors
12000 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
12001 throw new IllegalArgumentException("File descriptors passed in Bundle");
12002 }
12003
12004 boolean doNext;
12005
12006 final long origId = Binder.clearCallingIdentity();
12007
12008 synchronized(this) {
12009 doNext = finishReceiverLocked(
12010 who, resultCode, resultData, resultExtras, resultAbort, true);
12011 }
12012
12013 if (doNext) {
12014 processNextBroadcast(false);
12015 }
12016 trimApplications();
12017
12018 Binder.restoreCallingIdentity(origId);
12019 }
12020
Jeff Brown4d94a762010-09-23 11:33:28 -070012021 private final void logBroadcastReceiverDiscardLocked(BroadcastRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012022 if (r.nextReceiver > 0) {
12023 Object curReceiver = r.receivers.get(r.nextReceiver-1);
12024 if (curReceiver instanceof BroadcastFilter) {
12025 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080012026 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012027 System.identityHashCode(r),
12028 r.intent.getAction(),
12029 r.nextReceiver - 1,
12030 System.identityHashCode(bf));
12031 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080012032 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012033 System.identityHashCode(r),
12034 r.intent.getAction(),
12035 r.nextReceiver - 1,
12036 ((ResolveInfo)curReceiver).toString());
12037 }
12038 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012039 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012040 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080012041 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012042 System.identityHashCode(r),
12043 r.intent.getAction(),
12044 r.nextReceiver,
12045 "NONE");
12046 }
12047 }
12048
Jeff Brown4d94a762010-09-23 11:33:28 -070012049 private final void setBroadcastTimeoutLocked(long timeoutTime) {
12050 if (! mPendingBroadcastTimeoutMessage) {
12051 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
12052 mHandler.sendMessageAtTime(msg, timeoutTime);
12053 mPendingBroadcastTimeoutMessage = true;
12054 }
12055 }
12056
12057 private final void cancelBroadcastTimeoutLocked() {
12058 if (mPendingBroadcastTimeoutMessage) {
12059 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
12060 mPendingBroadcastTimeoutMessage = false;
12061 }
12062 }
12063
12064 private final void broadcastTimeoutLocked(boolean fromMsg) {
12065 if (fromMsg) {
12066 mPendingBroadcastTimeoutMessage = false;
12067 }
12068
12069 if (mOrderedBroadcasts.size() == 0) {
12070 return;
12071 }
12072
12073 long now = SystemClock.uptimeMillis();
12074 BroadcastRecord r = mOrderedBroadcasts.get(0);
12075 if (fromMsg) {
12076 if (mDidDexOpt) {
12077 // Delay timeouts until dexopt finishes.
12078 mDidDexOpt = false;
12079 long timeoutTime = SystemClock.uptimeMillis() + BROADCAST_TIMEOUT;
12080 setBroadcastTimeoutLocked(timeoutTime);
12081 return;
12082 }
12083 if (! mProcessesReady) {
12084 // Only process broadcast timeouts if the system is ready. That way
12085 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
12086 // to do heavy lifting for system up.
12087 return;
12088 }
12089
12090 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
12091 if (timeoutTime > now) {
12092 // We can observe premature timeouts because we do not cancel and reset the
12093 // broadcast timeout message after each receiver finishes. Instead, we set up
12094 // an initial timeout then kick it down the road a little further as needed
12095 // when it expires.
12096 if (DEBUG_BROADCAST) Slog.v(TAG,
12097 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
12098 + timeoutTime);
12099 setBroadcastTimeoutLocked(timeoutTime);
12100 return;
12101 }
12102 }
12103
12104 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver
12105 + ", started " + (now - r.receiverTime) + "ms ago");
12106 r.receiverTime = now;
12107 r.anrCount++;
12108
12109 // Current receiver has passed its expiration date.
12110 if (r.nextReceiver <= 0) {
12111 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
12112 return;
12113 }
12114
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012115 ProcessRecord app = null;
12116 String anrMessage = null;
12117
Jeff Brown4d94a762010-09-23 11:33:28 -070012118 Object curReceiver = r.receivers.get(r.nextReceiver-1);
12119 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
12120 logBroadcastReceiverDiscardLocked(r);
12121 if (curReceiver instanceof BroadcastFilter) {
12122 BroadcastFilter bf = (BroadcastFilter)curReceiver;
12123 if (bf.receiverList.pid != 0
12124 && bf.receiverList.pid != MY_PID) {
12125 synchronized (this.mPidsSelfLocked) {
12126 app = this.mPidsSelfLocked.get(
12127 bf.receiverList.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012128 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012129 }
Jeff Brown4d94a762010-09-23 11:33:28 -070012130 } else {
12131 app = r.curApp;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012132 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012133
Jeff Brown4d94a762010-09-23 11:33:28 -070012134 if (app != null) {
12135 anrMessage = "Broadcast of " + r.intent.toString();
12136 }
12137
12138 if (mPendingBroadcast == r) {
12139 mPendingBroadcast = null;
12140 }
12141
12142 // Move on to the next receiver.
12143 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
12144 r.resultExtras, r.resultAbort, true);
12145 scheduleBroadcastsLocked();
12146
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012147 if (anrMessage != null) {
Jeff Brown4d94a762010-09-23 11:33:28 -070012148 // Post the ANR to the handler since we do not want to process ANRs while
12149 // potentially holding our lock.
12150 mHandler.post(new AppNotResponding(app, anrMessage));
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012151 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012152 }
12153
12154 private final void processCurBroadcastLocked(BroadcastRecord r,
12155 ProcessRecord app) throws RemoteException {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012156 if (DEBUG_BROADCAST) Slog.v(TAG,
12157 "Process cur broadcast " + r + " for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012158 if (app.thread == null) {
12159 throw new RemoteException();
12160 }
12161 r.receiver = app.thread.asBinder();
12162 r.curApp = app;
12163 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012164 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012165
12166 // Tell the application to launch this receiver.
12167 r.intent.setComponent(r.curComponent);
12168
12169 boolean started = false;
12170 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012171 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012172 "Delivering to component " + r.curComponent
12173 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070012174 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012175 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
Dianne Hackborne2515ee2011-04-27 18:52:56 -040012176 compatibilityInfoForPackageLocked(r.curReceiver.applicationInfo),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012177 r.resultCode, r.resultData, r.resultExtras, r.ordered);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012178 if (DEBUG_BROADCAST) Slog.v(TAG,
12179 "Process cur broadcast " + r + " DELIVERED for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012180 started = true;
12181 } finally {
12182 if (!started) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012183 if (DEBUG_BROADCAST) Slog.v(TAG,
12184 "Process cur broadcast " + r + ": NOT STARTED!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012185 r.receiver = null;
12186 r.curApp = null;
12187 app.curReceiver = null;
12188 }
12189 }
12190
12191 }
12192
Jeff Brown4d94a762010-09-23 11:33:28 -070012193 static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012194 Intent intent, int resultCode, String data, Bundle extras,
12195 boolean ordered, boolean sticky) throws RemoteException {
Jeff Brown4d94a762010-09-23 11:33:28 -070012196 // Send the intent to the receiver asynchronously using one-way binder calls.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012197 if (app != null && app.thread != null) {
12198 // If we have an app thread, do the call through that so it is
12199 // correctly ordered with other one-way calls.
12200 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012201 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012202 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012203 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012204 }
12205 }
12206
Jeff Brown4d94a762010-09-23 11:33:28 -070012207 private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012208 BroadcastFilter filter, boolean ordered) {
12209 boolean skip = false;
12210 if (filter.requiredPermission != null) {
12211 int perm = checkComponentPermission(filter.requiredPermission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080012212 r.callingPid, r.callingUid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012213 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012214 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012215 + r.intent.toString()
12216 + " from " + r.callerPackage + " (pid="
12217 + r.callingPid + ", uid=" + r.callingUid + ")"
12218 + " requires " + filter.requiredPermission
12219 + " due to registered receiver " + filter);
12220 skip = true;
12221 }
12222 }
12223 if (r.requiredPermission != null) {
12224 int perm = checkComponentPermission(r.requiredPermission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080012225 filter.receiverList.pid, filter.receiverList.uid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012226 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012227 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012228 + r.intent.toString()
12229 + " to " + filter.receiverList.app
12230 + " (pid=" + filter.receiverList.pid
12231 + ", uid=" + filter.receiverList.uid + ")"
12232 + " requires " + r.requiredPermission
12233 + " due to sender " + r.callerPackage
12234 + " (uid " + r.callingUid + ")");
12235 skip = true;
12236 }
12237 }
12238
12239 if (!skip) {
12240 // If this is not being sent as an ordered broadcast, then we
12241 // don't want to touch the fields that keep track of the current
12242 // state of ordered broadcasts.
12243 if (ordered) {
12244 r.receiver = filter.receiverList.receiver.asBinder();
12245 r.curFilter = filter;
12246 filter.receiverList.curBroadcast = r;
12247 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012248 if (filter.receiverList.app != null) {
12249 // Bump hosting application to no longer be in background
12250 // scheduling class. Note that we can't do that if there
12251 // isn't an app... but we can only be in that case for
12252 // things that directly call the IActivityManager API, which
12253 // are already core system stuff so don't matter for this.
12254 r.curApp = filter.receiverList.app;
12255 filter.receiverList.app.curReceiver = r;
12256 updateOomAdjLocked();
12257 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012258 }
12259 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012260 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012261 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070012262 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012263 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012264 }
Jeff Brown4d94a762010-09-23 11:33:28 -070012265 performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012266 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012267 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012268 if (ordered) {
12269 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
12270 }
12271 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012272 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012273 if (ordered) {
12274 r.receiver = null;
12275 r.curFilter = null;
12276 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012277 if (filter.receiverList.app != null) {
12278 filter.receiverList.app.curReceiver = null;
12279 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012280 }
12281 }
12282 }
12283 }
12284
Dianne Hackborn12527f92009-11-11 17:39:50 -080012285 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
12286 if (r.callingUid < 0) {
12287 // This was from a registerReceiver() call; ignore it.
12288 return;
12289 }
12290 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
12291 MAX_BROADCAST_HISTORY-1);
12292 r.finishTime = SystemClock.uptimeMillis();
12293 mBroadcastHistory[0] = r;
12294 }
12295
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012296 private final void processNextBroadcast(boolean fromMsg) {
12297 synchronized(this) {
12298 BroadcastRecord r;
12299
Joe Onorato8a9b2202010-02-26 18:56:32 -080012300 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012301 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070012302 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012303
12304 updateCpuStats();
12305
12306 if (fromMsg) {
12307 mBroadcastsScheduled = false;
12308 }
12309
12310 // First, deliver any non-serialized broadcasts right away.
12311 while (mParallelBroadcasts.size() > 0) {
12312 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080012313 r.dispatchTime = SystemClock.uptimeMillis();
Dianne Hackbornd99b2932011-08-18 14:39:58 -070012314 r.dispatchClockTime = System.currentTimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012315 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080012316 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012317 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012318 for (int i=0; i<N; i++) {
12319 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012320 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070012321 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012322 + target + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070012323 deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012324 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080012325 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012326 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012327 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012328 }
12329
12330 // Now take care of the next serialized one...
12331
12332 // If we are waiting for a process to come up to handle the next
12333 // broadcast, then do nothing at this point. Just in case, we
12334 // check that the process we're waiting for still exists.
12335 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070012336 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012337 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070012338 + mPendingBroadcast.curApp);
12339 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012340
12341 boolean isDead;
12342 synchronized (mPidsSelfLocked) {
12343 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
12344 }
12345 if (!isDead) {
12346 // It's still alive, so keep waiting
12347 return;
12348 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012349 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012350 + " died before responding to broadcast");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012351 mPendingBroadcast.state = BroadcastRecord.IDLE;
12352 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012353 mPendingBroadcast = null;
12354 }
12355 }
12356
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012357 boolean looped = false;
12358
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012359 do {
12360 if (mOrderedBroadcasts.size() == 0) {
12361 // No more broadcasts pending, so all done!
12362 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012363 if (looped) {
12364 // If we had finished the last ordered broadcast, then
12365 // make sure all processes have correct oom and sched
12366 // adjustments.
12367 updateOomAdjLocked();
12368 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012369 return;
12370 }
12371 r = mOrderedBroadcasts.get(0);
12372 boolean forceReceive = false;
12373
12374 // Ensure that even if something goes awry with the timeout
12375 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050012376 // and continue to make progress.
12377 //
12378 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
Jeff Brown4d94a762010-09-23 11:33:28 -070012379 // receivers don't get executed with timeouts. They're intended for
Jeff Hamiltonacf84742010-05-25 22:10:18 -050012380 // one time heavy lifting after system upgrades and can take
12381 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012382 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012383 if (mProcessesReady && r.dispatchTime > 0) {
Jeff Hamiltonacf84742010-05-25 22:10:18 -050012384 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012385 if ((numReceivers > 0) &&
12386 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012387 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012388 + " now=" + now
12389 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080012390 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012391 + " intent=" + r.intent
12392 + " numReceivers=" + numReceivers
12393 + " nextReceiver=" + r.nextReceiver
12394 + " state=" + r.state);
Jeff Brown4d94a762010-09-23 11:33:28 -070012395 broadcastTimeoutLocked(false); // forcibly finish this broadcast
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012396 forceReceive = true;
12397 r.state = BroadcastRecord.IDLE;
12398 }
12399 }
12400
12401 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012402 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012403 "processNextBroadcast() called when not idle (state="
12404 + r.state + ")");
12405 return;
12406 }
12407
12408 if (r.receivers == null || r.nextReceiver >= numReceivers
12409 || r.resultAbort || forceReceive) {
12410 // No more receivers for this broadcast! Send the final
12411 // result if requested...
12412 if (r.resultTo != null) {
12413 try {
12414 if (DEBUG_BROADCAST) {
12415 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012416 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012417 + " seq=" + seq + " app=" + r.callerApp);
12418 }
Jeff Brown4d94a762010-09-23 11:33:28 -070012419 performReceiveLocked(r.callerApp, r.resultTo,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012420 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012421 r.resultData, r.resultExtras, false, false);
Johannes Carlssonb5a86542010-10-27 10:08:10 +020012422 // Set this to null so that the reference
12423 // (local and remote) isnt kept in the mBroadcastHistory.
12424 r.resultTo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012425 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012426 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012427 }
12428 }
12429
Joe Onorato8a9b2202010-02-26 18:56:32 -080012430 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
Jeff Brown4d94a762010-09-23 11:33:28 -070012431 cancelBroadcastTimeoutLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012432
Joe Onorato8a9b2202010-02-26 18:56:32 -080012433 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012434 + r);
12435
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012436 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080012437 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012438 mOrderedBroadcasts.remove(0);
12439 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012440 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012441 continue;
12442 }
12443 } while (r == null);
12444
12445 // Get the next receiver...
12446 int recIdx = r.nextReceiver++;
12447
12448 // Keep track of when this receiver started, and make sure there
12449 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080012450 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012451 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080012452 r.dispatchTime = r.receiverTime;
Dianne Hackbornd99b2932011-08-18 14:39:58 -070012453 r.dispatchClockTime = System.currentTimeMillis();
Joe Onorato8a9b2202010-02-26 18:56:32 -080012454 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012455 + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070012456 }
12457 if (! mPendingBroadcastTimeoutMessage) {
12458 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012459 if (DEBUG_BROADCAST) Slog.v(TAG,
Jeff Brown4d94a762010-09-23 11:33:28 -070012460 "Submitting BROADCAST_TIMEOUT_MSG for " + r + " at " + timeoutTime);
12461 setBroadcastTimeoutLocked(timeoutTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012462 }
12463
12464 Object nextReceiver = r.receivers.get(recIdx);
12465 if (nextReceiver instanceof BroadcastFilter) {
12466 // Simple case: this is a registered receiver who gets
12467 // a direct call.
12468 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012469 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070012470 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012471 + filter + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070012472 deliverToRegisteredReceiverLocked(r, filter, r.ordered);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012473 if (r.receiver == null || !r.ordered) {
12474 // The receiver has already finished, so schedule to
12475 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070012476 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
12477 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012478 r.state = BroadcastRecord.IDLE;
12479 scheduleBroadcastsLocked();
12480 }
12481 return;
12482 }
12483
12484 // Hard case: need to instantiate the receiver, possibly
12485 // starting its application process to host it.
12486
12487 ResolveInfo info =
12488 (ResolveInfo)nextReceiver;
12489
12490 boolean skip = false;
12491 int perm = checkComponentPermission(info.activityInfo.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080012492 r.callingPid, r.callingUid, info.activityInfo.applicationInfo.uid,
12493 info.activityInfo.exported);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012494 if (perm != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080012495 if (!info.activityInfo.exported) {
12496 Slog.w(TAG, "Permission Denial: broadcasting "
12497 + r.intent.toString()
12498 + " from " + r.callerPackage + " (pid=" + r.callingPid
12499 + ", uid=" + r.callingUid + ")"
12500 + " is not exported from uid " + info.activityInfo.applicationInfo.uid
12501 + " due to receiver " + info.activityInfo.packageName
12502 + "/" + info.activityInfo.name);
12503 } else {
12504 Slog.w(TAG, "Permission Denial: broadcasting "
12505 + r.intent.toString()
12506 + " from " + r.callerPackage + " (pid=" + r.callingPid
12507 + ", uid=" + r.callingUid + ")"
12508 + " requires " + info.activityInfo.permission
12509 + " due to receiver " + info.activityInfo.packageName
12510 + "/" + info.activityInfo.name);
12511 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012512 skip = true;
12513 }
Dianne Hackbornd99b2932011-08-18 14:39:58 -070012514 if (info.activityInfo.applicationInfo.uid != Process.SYSTEM_UID &&
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012515 r.requiredPermission != null) {
12516 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012517 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012518 checkPermission(r.requiredPermission,
12519 info.activityInfo.applicationInfo.packageName);
12520 } catch (RemoteException e) {
12521 perm = PackageManager.PERMISSION_DENIED;
12522 }
12523 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012524 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012525 + r.intent + " to "
12526 + info.activityInfo.applicationInfo.packageName
12527 + " requires " + r.requiredPermission
12528 + " due to sender " + r.callerPackage
12529 + " (uid " + r.callingUid + ")");
12530 skip = true;
12531 }
12532 }
12533 if (r.curApp != null && r.curApp.crashing) {
12534 // If the target process is crashing, just skip it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012535 if (DEBUG_BROADCAST) Slog.v(TAG,
12536 "Skipping deliver ordered " + r + " to " + r.curApp
12537 + ": process crashing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012538 skip = true;
12539 }
12540
12541 if (skip) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012542 if (DEBUG_BROADCAST) Slog.v(TAG,
12543 "Skipping delivery of ordered " + r + " for whatever reason");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012544 r.receiver = null;
12545 r.curFilter = null;
12546 r.state = BroadcastRecord.IDLE;
12547 scheduleBroadcastsLocked();
12548 return;
12549 }
12550
12551 r.state = BroadcastRecord.APP_RECEIVE;
12552 String targetProcess = info.activityInfo.processName;
12553 r.curComponent = new ComponentName(
12554 info.activityInfo.applicationInfo.packageName,
12555 info.activityInfo.name);
12556 r.curReceiver = info.activityInfo;
12557
Dianne Hackborne7f97212011-02-24 14:40:20 -080012558 // Broadcast is being executed, its package can't be stopped.
12559 try {
12560 AppGlobals.getPackageManager().setPackageStoppedState(
12561 r.curComponent.getPackageName(), false);
12562 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -080012563 } catch (IllegalArgumentException e) {
12564 Slog.w(TAG, "Failed trying to unstop package "
12565 + r.curComponent.getPackageName() + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -080012566 }
12567
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012568 // Is this receiver's application already running?
12569 ProcessRecord app = getProcessRecordLocked(targetProcess,
12570 info.activityInfo.applicationInfo.uid);
12571 if (app != null && app.thread != null) {
12572 try {
Dianne Hackborn6c418d52011-06-29 14:05:33 -070012573 app.addPackage(info.activityInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012574 processCurBroadcastLocked(r, app);
12575 return;
12576 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012577 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012578 + r.curComponent, e);
12579 }
12580
12581 // If a dead object exception was thrown -- fall through to
12582 // restart the application.
12583 }
12584
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012585 // Not running -- get it started, to be executed when the app comes up.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012586 if (DEBUG_BROADCAST) Slog.v(TAG,
12587 "Need to start app " + targetProcess + " for broadcast " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012588 if ((r.curApp=startProcessLocked(targetProcess,
12589 info.activityInfo.applicationInfo, true,
12590 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012591 "broadcast", r.curComponent,
12592 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
12593 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012594 // Ah, this recipient is unavailable. Finish it if necessary,
12595 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080012596 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012597 + info.activityInfo.applicationInfo.packageName + "/"
12598 + info.activityInfo.applicationInfo.uid + " for broadcast "
12599 + r.intent + ": process is bad");
Jeff Brown4d94a762010-09-23 11:33:28 -070012600 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012601 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
12602 r.resultExtras, r.resultAbort, true);
12603 scheduleBroadcastsLocked();
12604 r.state = BroadcastRecord.IDLE;
12605 return;
12606 }
12607
12608 mPendingBroadcast = r;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012609 mPendingBroadcastRecvIndex = recIdx;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012610 }
12611 }
12612
12613 // =========================================================
12614 // INSTRUMENTATION
12615 // =========================================================
12616
12617 public boolean startInstrumentation(ComponentName className,
12618 String profileFile, int flags, Bundle arguments,
12619 IInstrumentationWatcher watcher) {
12620 // Refuse possible leaked file descriptors
12621 if (arguments != null && arguments.hasFileDescriptors()) {
12622 throw new IllegalArgumentException("File descriptors passed in Bundle");
12623 }
12624
12625 synchronized(this) {
12626 InstrumentationInfo ii = null;
12627 ApplicationInfo ai = null;
12628 try {
12629 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012630 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012631 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012632 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012633 } catch (PackageManager.NameNotFoundException e) {
12634 }
12635 if (ii == null) {
12636 reportStartInstrumentationFailure(watcher, className,
12637 "Unable to find instrumentation info for: " + className);
12638 return false;
12639 }
12640 if (ai == null) {
12641 reportStartInstrumentationFailure(watcher, className,
12642 "Unable to find instrumentation target package: " + ii.targetPackage);
12643 return false;
12644 }
12645
12646 int match = mContext.getPackageManager().checkSignatures(
12647 ii.targetPackage, ii.packageName);
12648 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
12649 String msg = "Permission Denial: starting instrumentation "
12650 + className + " from pid="
12651 + Binder.getCallingPid()
12652 + ", uid=" + Binder.getCallingPid()
12653 + " not allowed because package " + ii.packageName
12654 + " does not have a signature matching the target "
12655 + ii.targetPackage;
12656 reportStartInstrumentationFailure(watcher, className, msg);
12657 throw new SecurityException(msg);
12658 }
12659
12660 final long origId = Binder.clearCallingIdentity();
Christopher Tate3dacd842011-08-19 14:56:15 -070012661 // Instrumentation can kill and relaunch even persistent processes
12662 forceStopPackageLocked(ii.targetPackage, -1, true, false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012663 ProcessRecord app = addAppLocked(ai);
12664 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070012665 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012666 app.instrumentationProfileFile = profileFile;
12667 app.instrumentationArguments = arguments;
12668 app.instrumentationWatcher = watcher;
12669 app.instrumentationResultClass = className;
12670 Binder.restoreCallingIdentity(origId);
12671 }
12672
12673 return true;
12674 }
12675
12676 /**
12677 * Report errors that occur while attempting to start Instrumentation. Always writes the
12678 * error to the logs, but if somebody is watching, send the report there too. This enables
12679 * the "am" command to report errors with more information.
12680 *
12681 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
12682 * @param cn The component name of the instrumentation.
12683 * @param report The error report.
12684 */
12685 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
12686 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012687 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012688 try {
12689 if (watcher != null) {
12690 Bundle results = new Bundle();
12691 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
12692 results.putString("Error", report);
12693 watcher.instrumentationStatus(cn, -1, results);
12694 }
12695 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012696 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012697 }
12698 }
12699
12700 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
12701 if (app.instrumentationWatcher != null) {
12702 try {
12703 // NOTE: IInstrumentationWatcher *must* be oneway here
12704 app.instrumentationWatcher.instrumentationFinished(
12705 app.instrumentationClass,
12706 resultCode,
12707 results);
12708 } catch (RemoteException e) {
12709 }
12710 }
12711 app.instrumentationWatcher = null;
12712 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070012713 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012714 app.instrumentationProfileFile = null;
12715 app.instrumentationArguments = null;
12716
Christopher Tate3dacd842011-08-19 14:56:15 -070012717 forceStopPackageLocked(app.processName, -1, false, false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012718 }
12719
12720 public void finishInstrumentation(IApplicationThread target,
12721 int resultCode, Bundle results) {
12722 // Refuse possible leaked file descriptors
12723 if (results != null && results.hasFileDescriptors()) {
12724 throw new IllegalArgumentException("File descriptors passed in Intent");
12725 }
12726
12727 synchronized(this) {
12728 ProcessRecord app = getRecordForAppLocked(target);
12729 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012730 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012731 return;
12732 }
12733 final long origId = Binder.clearCallingIdentity();
12734 finishInstrumentationLocked(app, resultCode, results);
12735 Binder.restoreCallingIdentity(origId);
12736 }
12737 }
12738
12739 // =========================================================
12740 // CONFIGURATION
12741 // =========================================================
12742
12743 public ConfigurationInfo getDeviceConfigurationInfo() {
12744 ConfigurationInfo config = new ConfigurationInfo();
12745 synchronized (this) {
12746 config.reqTouchScreen = mConfiguration.touchscreen;
12747 config.reqKeyboardType = mConfiguration.keyboard;
12748 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070012749 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
12750 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012751 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
12752 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070012753 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
12754 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012755 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
12756 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070012757 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012758 }
12759 return config;
12760 }
12761
12762 public Configuration getConfiguration() {
12763 Configuration ci;
12764 synchronized(this) {
12765 ci = new Configuration(mConfiguration);
12766 }
12767 return ci;
12768 }
12769
Dianne Hackborn31ca8542011-07-19 14:58:28 -070012770 public void updatePersistentConfiguration(Configuration values) {
12771 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
12772 "updateConfiguration()");
12773 enforceCallingPermission(android.Manifest.permission.WRITE_SETTINGS,
12774 "updateConfiguration()");
12775 if (values == null) {
12776 throw new NullPointerException("Configuration must not be null");
12777 }
12778
12779 synchronized(this) {
12780 final long origId = Binder.clearCallingIdentity();
12781 updateConfigurationLocked(values, null, true);
12782 Binder.restoreCallingIdentity(origId);
12783 }
12784 }
12785
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012786 public void updateConfiguration(Configuration values) {
12787 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
12788 "updateConfiguration()");
12789
12790 synchronized(this) {
12791 if (values == null && mWindowManager != null) {
12792 // sentinel: fetch the current configuration from the window manager
12793 values = mWindowManager.computeNewConfiguration();
12794 }
Dianne Hackborn7d608422011-08-07 16:24:18 -070012795
12796 if (mWindowManager != null) {
12797 mProcessList.applyDisplaySize(mWindowManager);
12798 }
12799
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012800 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn31ca8542011-07-19 14:58:28 -070012801 if (values != null) {
12802 Settings.System.clearConfiguration(values);
12803 }
12804 updateConfigurationLocked(values, null, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012805 Binder.restoreCallingIdentity(origId);
12806 }
12807 }
12808
12809 /**
12810 * Do either or both things: (1) change the current configuration, and (2)
12811 * make sure the given activity is running with the (now) current
12812 * configuration. Returns true if the activity has been left running, or
12813 * false if <var>starting</var> is being destroyed to match the new
12814 * configuration.
Dianne Hackborn31ca8542011-07-19 14:58:28 -070012815 * @param persistent TODO
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012816 */
12817 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn31ca8542011-07-19 14:58:28 -070012818 ActivityRecord starting, boolean persistent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012819 int changes = 0;
12820
12821 boolean kept = true;
12822
12823 if (values != null) {
12824 Configuration newConfig = new Configuration(mConfiguration);
12825 changes = newConfig.updateFrom(values);
12826 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070012827 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012828 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012829 }
12830
Doug Zongker2bec3d42009-12-04 12:52:44 -080012831 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012832
12833 if (values.locale != null) {
12834 saveLocaleLocked(values.locale,
12835 !values.locale.equals(mConfiguration.locale),
12836 values.userSetLocale);
12837 }
12838
Dianne Hackborne36d6e22010-02-17 19:46:25 -080012839 mConfigurationSeq++;
12840 if (mConfigurationSeq <= 0) {
12841 mConfigurationSeq = 1;
12842 }
12843 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012844 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012845 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080012846
12847 AttributeCache ac = AttributeCache.instance();
12848 if (ac != null) {
12849 ac.updateConfiguration(mConfiguration);
12850 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012851
Dianne Hackborn2f0b1752011-05-31 17:59:49 -070012852 // Make sure all resources in our process are updated
12853 // right now, so that anyone who is going to retrieve
12854 // resource values after we return will be sure to get
12855 // the new ones. This is especially important during
12856 // boot, where the first config change needs to guarantee
12857 // all resources have that config before following boot
12858 // code is executed.
12859 mSystemThread.applyConfigurationToResources(newConfig);
12860
Dianne Hackborn31ca8542011-07-19 14:58:28 -070012861 if (persistent && Settings.System.hasInterestingConfigurationChanges(changes)) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080012862 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
12863 msg.obj = new Configuration(mConfiguration);
12864 mHandler.sendMessage(msg);
12865 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012866
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012867 for (int i=mLruProcesses.size()-1; i>=0; i--) {
12868 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012869 try {
12870 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012871 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070012872 + app.processName + " new config " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012873 app.thread.scheduleConfigurationChanged(mConfiguration);
12874 }
12875 } catch (Exception e) {
12876 }
12877 }
12878 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012879 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
12880 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012881 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
12882 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080012883 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
12884 broadcastIntentLocked(null, null,
12885 new Intent(Intent.ACTION_LOCALE_CHANGED),
12886 null, null, 0, null, null,
12887 null, false, false, MY_PID, Process.SYSTEM_UID);
12888 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012889 }
12890 }
12891
12892 if (changes != 0 && starting == null) {
12893 // If the configuration changed, and the caller is not already
12894 // in the process of starting an activity, then find the top
12895 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012896 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012897 }
12898
12899 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070012900 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
Dianne Hackborn5f4d6432010-12-21 20:40:11 -080012901 // And we need to make sure at this point that all other activities
12902 // are made visible with the correct configuration.
12903 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012904 }
12905
Dianne Hackborne36d6e22010-02-17 19:46:25 -080012906 if (values != null && mWindowManager != null) {
12907 mWindowManager.setNewConfiguration(mConfiguration);
12908 }
12909
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012910 return kept;
12911 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012912
12913 /**
12914 * Save the locale. You must be inside a synchronized (this) block.
12915 */
12916 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
12917 if(isDiff) {
12918 SystemProperties.set("user.language", l.getLanguage());
12919 SystemProperties.set("user.region", l.getCountry());
12920 }
12921
12922 if(isPersist) {
12923 SystemProperties.set("persist.sys.language", l.getLanguage());
12924 SystemProperties.set("persist.sys.country", l.getCountry());
12925 SystemProperties.set("persist.sys.localevar", l.getVariant());
12926 }
12927 }
12928
12929 // =========================================================
12930 // LIFETIME MANAGEMENT
12931 // =========================================================
12932
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012933 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
12934 ProcessRecord TOP_APP, boolean recursed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012935 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012936 // This adjustment has already been computed. If we are calling
12937 // from the top, we may have already computed our adjustment with
12938 // an earlier hidden adjustment that isn't really for us... if
12939 // so, use the new hidden adjustment.
12940 if (!recursed && app.hidden) {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070012941 app.curAdj = app.curRawAdj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012942 }
Dianne Hackbornc68c9132011-07-29 01:25:18 -070012943 return app.curRawAdj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012944 }
12945
12946 if (app.thread == null) {
12947 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012948 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborn7d608422011-08-07 16:24:18 -070012949 return (app.curAdj=ProcessList.EMPTY_APP_ADJ);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012950 }
12951
Dianne Hackbornc68c9132011-07-29 01:25:18 -070012952 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
12953 app.adjSource = null;
12954 app.adjTarget = null;
12955 app.empty = false;
12956 app.hidden = false;
12957
12958 final int activitiesSize = app.activities.size();
12959
Dianne Hackborn7d608422011-08-07 16:24:18 -070012960 if (app.maxAdj <= ProcessList.FOREGROUND_APP_ADJ) {
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012961 // The max adjustment doesn't allow this app to be anything
12962 // below foreground, so it is not worth doing work for it.
12963 app.adjType = "fixed";
12964 app.adjSeq = mAdjSeq;
12965 app.curRawAdj = app.maxAdj;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070012966 app.foregroundActivities = false;
Dianne Hackborn287952c2010-09-22 22:34:31 -070012967 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012968 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070012969 // System process can do UI, and when they do we want to have
12970 // them trim their memory after the user leaves the UI. To
12971 // facilitate this, here we need to determine whether or not it
12972 // is currently showing UI.
12973 app.systemNoUi = true;
12974 if (app == TOP_APP) {
12975 app.systemNoUi = false;
12976 } else if (activitiesSize > 0) {
12977 for (int j = 0; j < activitiesSize; j++) {
12978 final ActivityRecord r = app.activities.get(j);
12979 if (r.visible) {
12980 app.systemNoUi = false;
12981 break;
12982 }
12983 }
12984 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012985 return (app.curAdj=app.maxAdj);
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012986 }
12987
12988 final boolean hadForegroundActivities = app.foregroundActivities;
12989
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070012990 app.foregroundActivities = false;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070012991 app.keeping = false;
12992 app.systemNoUi = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012993
The Android Open Source Project4df24232009-03-05 14:34:35 -080012994 // Determine the importance of the process, starting with most
12995 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012996 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080012997 int schedGroup;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070012998 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012999 // The last app on the list is the foreground app.
Dianne Hackborn7d608422011-08-07 16:24:18 -070013000 adj = ProcessList.FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013001 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013002 app.adjType = "top-activity";
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013003 app.foregroundActivities = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013004 } else if (app.instrumentationClass != null) {
13005 // Don't want to kill running instrumentation.
Dianne Hackborn7d608422011-08-07 16:24:18 -070013006 adj = ProcessList.FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013007 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013008 app.adjType = "instrumentation";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013009 } else if (app.curReceiver != null ||
13010 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
13011 // An app that is currently receiving a broadcast also
13012 // counts as being in the foreground.
Dianne Hackborn7d608422011-08-07 16:24:18 -070013013 adj = ProcessList.FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013014 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013015 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013016 } else if (app.executingServices.size() > 0) {
13017 // An app that is currently executing a service callback also
13018 // counts as being in the foreground.
Dianne Hackborn7d608422011-08-07 16:24:18 -070013019 adj = ProcessList.FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013020 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013021 app.adjType = "exec-service";
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013022 } else if (activitiesSize > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013023 // This app is in the background with paused activities.
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013024 // We inspect activities to potentially upgrade adjustment further below.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013025 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013026 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013027 app.hidden = true;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013028 app.adjType = "bg-activities";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013029 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013030 // A very not-needed process. If this is lower in the lru list,
13031 // we will push it in to the empty bucket.
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013032 adj = hiddenAdj;
13033 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013034 app.hidden = true;
13035 app.empty = true;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013036 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013037 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013038
13039 // Examine all activities if not already foreground.
13040 if (!app.foregroundActivities && activitiesSize > 0) {
13041 for (int j = 0; j < activitiesSize; j++) {
13042 final ActivityRecord r = app.activities.get(j);
13043 if (r.visible) {
13044 // App has a visible activity; only upgrade adjustment.
Dianne Hackborn7d608422011-08-07 16:24:18 -070013045 if (adj > ProcessList.VISIBLE_APP_ADJ) {
13046 adj = ProcessList.VISIBLE_APP_ADJ;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013047 app.adjType = "visible";
13048 }
13049 schedGroup = Process.THREAD_GROUP_DEFAULT;
13050 app.hidden = false;
13051 app.foregroundActivities = true;
13052 break;
13053 } else if (r.state == ActivityState.PAUSING || r.state == ActivityState.PAUSED
13054 || r.state == ActivityState.STOPPING) {
13055 // Only upgrade adjustment.
Dianne Hackborn7d608422011-08-07 16:24:18 -070013056 if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
13057 adj = ProcessList.PERCEPTIBLE_APP_ADJ;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013058 app.adjType = "stopping";
13059 }
13060 app.foregroundActivities = true;
13061 }
13062 }
13063 }
13064
Dianne Hackborn7d608422011-08-07 16:24:18 -070013065 if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn83a6f452011-01-27 17:17:19 -080013066 if (app.foregroundServices) {
13067 // The user is aware of this app, so make it visible.
Dianne Hackborn7d608422011-08-07 16:24:18 -070013068 adj = ProcessList.PERCEPTIBLE_APP_ADJ;
Dianne Hackborn98cfebc2011-10-18 13:17:33 -070013069 app.hidden = false;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080013070 app.adjType = "foreground-service";
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013071 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080013072 } else if (app.forcingToForeground != null) {
13073 // The user is aware of this app, so make it visible.
Dianne Hackborn7d608422011-08-07 16:24:18 -070013074 adj = ProcessList.PERCEPTIBLE_APP_ADJ;
Dianne Hackborn98cfebc2011-10-18 13:17:33 -070013075 app.hidden = false;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080013076 app.adjType = "force-foreground";
13077 app.adjSource = app.forcingToForeground;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013078 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080013079 }
13080 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013081
Dianne Hackborn7d608422011-08-07 16:24:18 -070013082 if (adj > ProcessList.HEAVY_WEIGHT_APP_ADJ && app == mHeavyWeightProcess) {
Dianne Hackborn83a6f452011-01-27 17:17:19 -080013083 // We don't want to kill the current heavy-weight process.
Dianne Hackborn7d608422011-08-07 16:24:18 -070013084 adj = ProcessList.HEAVY_WEIGHT_APP_ADJ;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080013085 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborn98cfebc2011-10-18 13:17:33 -070013086 app.hidden = false;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080013087 app.adjType = "heavy";
13088 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013089
Dianne Hackborn7d608422011-08-07 16:24:18 -070013090 if (adj > ProcessList.HOME_APP_ADJ && app == mHomeProcess) {
Dianne Hackborn83a6f452011-01-27 17:17:19 -080013091 // This process is hosting what we currently consider to be the
13092 // home app, so we don't want to let it go into the background.
Dianne Hackborn7d608422011-08-07 16:24:18 -070013093 adj = ProcessList.HOME_APP_ADJ;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080013094 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborn98cfebc2011-10-18 13:17:33 -070013095 app.hidden = false;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080013096 app.adjType = "home";
13097 }
Dianne Hackborn98cfebc2011-10-18 13:17:33 -070013098
13099 if (false) Slog.i(TAG, "OOM " + app + ": initial adj=" + adj
13100 + " reason=" + app.adjType);
13101
The Android Open Source Project4df24232009-03-05 14:34:35 -080013102 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013103 // there are applications dependent on our services or providers, but
13104 // this gives us a baseline and makes sure we don't get into an
13105 // infinite recursion.
13106 app.adjSeq = mAdjSeq;
13107 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013108
Christopher Tate6fa95972009-06-05 18:43:55 -070013109 if (mBackupTarget != null && app == mBackupTarget.app) {
13110 // If possible we want to avoid killing apps while they're being backed up
Dianne Hackborn7d608422011-08-07 16:24:18 -070013111 if (adj > ProcessList.BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013112 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Dianne Hackborn7d608422011-08-07 16:24:18 -070013113 adj = ProcessList.BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013114 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013115 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070013116 }
13117 }
13118
Dianne Hackborn7d608422011-08-07 16:24:18 -070013119 if (app.services.size() != 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013120 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013121 final long now = SystemClock.uptimeMillis();
13122 // This process is more important if the top activity is
13123 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070013124 Iterator<ServiceRecord> jt = app.services.iterator();
Dianne Hackborn7d608422011-08-07 16:24:18 -070013125 while (jt.hasNext() && adj > ProcessList.FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070013126 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013127 if (s.startRequested) {
Dianne Hackborn98cfebc2011-10-18 13:17:33 -070013128 if (app.hasShownUi && app != mHomeProcess) {
Dianne Hackbornf0754f5b2011-07-21 16:02:07 -070013129 // If this process has shown some UI, let it immediately
13130 // go to the LRU list because it may be pretty heavy with
13131 // UI stuff. We'll tag it with a label just to help
13132 // debug and understand what is going on.
Dianne Hackborn7d608422011-08-07 16:24:18 -070013133 if (adj > ProcessList.SECONDARY_SERVER_ADJ) {
Dianne Hackbornf0754f5b2011-07-21 16:02:07 -070013134 app.adjType = "started-bg-ui-services";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013135 }
Dianne Hackbornf0754f5b2011-07-21 16:02:07 -070013136 } else {
13137 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
13138 // This service has seen some activity within
13139 // recent memory, so we will keep its process ahead
13140 // of the background processes.
Dianne Hackborn7d608422011-08-07 16:24:18 -070013141 if (adj > ProcessList.SECONDARY_SERVER_ADJ) {
13142 adj = ProcessList.SECONDARY_SERVER_ADJ;
Dianne Hackbornf0754f5b2011-07-21 16:02:07 -070013143 app.adjType = "started-services";
13144 app.hidden = false;
13145 }
13146 }
13147 // If we have let the service slide into the background
13148 // state, still have some text describing what it is doing
13149 // even though the service no longer has an impact.
Dianne Hackborn7d608422011-08-07 16:24:18 -070013150 if (adj > ProcessList.SECONDARY_SERVER_ADJ) {
Dianne Hackbornf0754f5b2011-07-21 16:02:07 -070013151 app.adjType = "started-bg-services";
13152 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013153 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070013154 // Don't kill this process because it is doing work; it
13155 // has said it is doing work.
13156 app.keeping = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013157 }
Dianne Hackborn7d608422011-08-07 16:24:18 -070013158 if (s.connections.size() > 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013159 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070013160 Iterator<ArrayList<ConnectionRecord>> kt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013161 = s.connections.values().iterator();
Dianne Hackborn7d608422011-08-07 16:24:18 -070013162 while (kt.hasNext() && adj > ProcessList.FOREGROUND_APP_ADJ) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070013163 ArrayList<ConnectionRecord> clist = kt.next();
Dianne Hackborn7d608422011-08-07 16:24:18 -070013164 for (int i=0; i<clist.size() && adj > ProcessList.FOREGROUND_APP_ADJ; i++) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070013165 // XXX should compute this based on the max of
13166 // all connected clients.
13167 ConnectionRecord cr = clist.get(i);
13168 if (cr.binding.client == app) {
13169 // Binding to ourself is not interesting.
13170 continue;
13171 }
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013172 if ((cr.flags&Context.BIND_WAIVE_PRIORITY) == 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070013173 ProcessRecord client = cr.binding.client;
Dianne Hackborn130b0d22011-07-26 22:07:48 -070013174 int clientAdj = adj;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070013175 int myHiddenAdj = hiddenAdj;
13176 if (myHiddenAdj > client.hiddenAdj) {
Dianne Hackborn7d608422011-08-07 16:24:18 -070013177 if (client.hiddenAdj >= ProcessList.VISIBLE_APP_ADJ) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070013178 myHiddenAdj = client.hiddenAdj;
13179 } else {
Dianne Hackborn7d608422011-08-07 16:24:18 -070013180 myHiddenAdj = ProcessList.VISIBLE_APP_ADJ;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070013181 }
13182 }
Dianne Hackborn130b0d22011-07-26 22:07:48 -070013183 clientAdj = computeOomAdjLocked(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070013184 client, myHiddenAdj, TOP_APP, true);
Dianne Hackborn130b0d22011-07-26 22:07:48 -070013185 String adjType = null;
13186 if ((cr.flags&Context.BIND_ALLOW_OOM_MANAGEMENT) != 0) {
13187 // Not doing bind OOM management, so treat
13188 // this guy more like a started service.
Dianne Hackborn98cfebc2011-10-18 13:17:33 -070013189 if (app.hasShownUi && app != mHomeProcess) {
Dianne Hackborn130b0d22011-07-26 22:07:48 -070013190 // If this process has shown some UI, let it immediately
13191 // go to the LRU list because it may be pretty heavy with
13192 // UI stuff. We'll tag it with a label just to help
13193 // debug and understand what is going on.
13194 if (adj > clientAdj) {
13195 adjType = "bound-bg-ui-services";
13196 }
Dianne Hackborn98cfebc2011-10-18 13:17:33 -070013197 app.hidden = false;
Dianne Hackborn130b0d22011-07-26 22:07:48 -070013198 clientAdj = adj;
13199 } else {
13200 if (now >= (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
13201 // This service has not seen activity within
13202 // recent memory, so allow it to drop to the
13203 // LRU list if there is no other reason to keep
13204 // it around. We'll also tag it with a label just
13205 // to help debug and undertand what is going on.
13206 if (adj > clientAdj) {
13207 adjType = "bound-bg-services";
13208 }
13209 clientAdj = adj;
13210 }
13211 }
13212 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070013213 if (adj > clientAdj) {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013214 // If this process has recently shown UI, and
13215 // the process that is binding to it is less
13216 // important than being visible, then we don't
13217 // care about the binding as much as we care
13218 // about letting this process get into the LRU
13219 // list to be killed and restarted if needed for
13220 // memory.
Dianne Hackborn98cfebc2011-10-18 13:17:33 -070013221 if (app.hasShownUi && app != mHomeProcess
13222 && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013223 adjType = "bound-bg-ui-services";
13224 } else {
13225 if ((cr.flags&(Context.BIND_ABOVE_CLIENT
13226 |Context.BIND_IMPORTANT)) != 0) {
13227 adj = clientAdj;
Dianne Hackborn7d608422011-08-07 16:24:18 -070013228 } else if (clientAdj >= ProcessList.VISIBLE_APP_ADJ) {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013229 adj = clientAdj;
13230 } else {
Dianne Hackborn7d608422011-08-07 16:24:18 -070013231 adj = ProcessList.VISIBLE_APP_ADJ;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013232 }
13233 if (!client.hidden) {
13234 app.hidden = false;
13235 }
13236 if (client.keeping) {
13237 app.keeping = true;
13238 }
13239 adjType = "service";
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070013240 }
Dianne Hackborn130b0d22011-07-26 22:07:48 -070013241 }
13242 if (adjType != null) {
13243 app.adjType = adjType;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070013244 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13245 .REASON_SERVICE_IN_USE;
13246 app.adjSource = cr.binding.client;
Dianne Hackborn905577f2011-09-07 18:31:28 -070013247 app.adjSourceOom = clientAdj;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070013248 app.adjTarget = s.name;
13249 }
13250 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
13251 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
13252 schedGroup = Process.THREAD_GROUP_DEFAULT;
13253 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013254 }
13255 }
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013256 if ((cr.flags&Context.BIND_ADJUST_WITH_ACTIVITY) != 0) {
13257 ActivityRecord a = cr.activity;
Dianne Hackborn7d608422011-08-07 16:24:18 -070013258 if (a != null && adj > ProcessList.FOREGROUND_APP_ADJ &&
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013259 (a.visible || a.state == ActivityState.RESUMED
13260 || a.state == ActivityState.PAUSING)) {
Dianne Hackborn7d608422011-08-07 16:24:18 -070013261 adj = ProcessList.FOREGROUND_APP_ADJ;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013262 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
13263 schedGroup = Process.THREAD_GROUP_DEFAULT;
13264 }
13265 app.hidden = false;
13266 app.adjType = "service";
13267 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13268 .REASON_SERVICE_IN_USE;
13269 app.adjSource = a;
Dianne Hackborn905577f2011-09-07 18:31:28 -070013270 app.adjSourceOom = adj;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013271 app.adjTarget = s.name;
13272 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013273 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013274 }
13275 }
13276 }
13277 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070013278
Dianne Hackborn287952c2010-09-22 22:34:31 -070013279 // Finally, if this process has active services running in it, we
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070013280 // would like to avoid killing it unless it would prevent the current
13281 // application from running. By default we put the process in
13282 // with the rest of the background processes; as we scan through
13283 // its services we may bump it up from there.
13284 if (adj > hiddenAdj) {
13285 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013286 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070013287 app.adjType = "bg-services";
13288 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013289 }
13290
Dianne Hackborn7d608422011-08-07 16:24:18 -070013291 if (app.pubProviders.size() != 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013292 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070013293 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn7d608422011-08-07 16:24:18 -070013294 while (jt.hasNext() && (adj > ProcessList.FOREGROUND_APP_ADJ
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013295 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070013296 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013297 if (cpr.clients.size() != 0) {
13298 Iterator<ProcessRecord> kt = cpr.clients.iterator();
Dianne Hackborn7d608422011-08-07 16:24:18 -070013299 while (kt.hasNext() && adj > ProcessList.FOREGROUND_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013300 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070013301 if (client == app) {
13302 // Being our own client is not interesting.
13303 continue;
13304 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013305 int myHiddenAdj = hiddenAdj;
13306 if (myHiddenAdj > client.hiddenAdj) {
Dianne Hackborn7d608422011-08-07 16:24:18 -070013307 if (client.hiddenAdj > ProcessList.FOREGROUND_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013308 myHiddenAdj = client.hiddenAdj;
13309 } else {
Dianne Hackborn7d608422011-08-07 16:24:18 -070013310 myHiddenAdj = ProcessList.FOREGROUND_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013311 }
13312 }
13313 int clientAdj = computeOomAdjLocked(
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013314 client, myHiddenAdj, TOP_APP, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013315 if (adj > clientAdj) {
Dianne Hackborn98cfebc2011-10-18 13:17:33 -070013316 if (app.hasShownUi && app != mHomeProcess
13317 && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013318 app.adjType = "bg-ui-provider";
13319 } else {
Dianne Hackborn7d608422011-08-07 16:24:18 -070013320 adj = clientAdj > ProcessList.FOREGROUND_APP_ADJ
13321 ? clientAdj : ProcessList.FOREGROUND_APP_ADJ;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013322 app.adjType = "provider";
13323 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013324 if (!client.hidden) {
13325 app.hidden = false;
13326 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070013327 if (client.keeping) {
13328 app.keeping = true;
13329 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070013330 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13331 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013332 app.adjSource = client;
Dianne Hackborn905577f2011-09-07 18:31:28 -070013333 app.adjSourceOom = clientAdj;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070013334 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013335 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013336 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
13337 schedGroup = Process.THREAD_GROUP_DEFAULT;
13338 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013339 }
13340 }
13341 // If the provider has external (non-framework) process
13342 // dependencies, ensure that its adjustment is at least
13343 // FOREGROUND_APP_ADJ.
13344 if (cpr.externals != 0) {
Dianne Hackborn7d608422011-08-07 16:24:18 -070013345 if (adj > ProcessList.FOREGROUND_APP_ADJ) {
13346 adj = ProcessList.FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013347 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013348 app.hidden = false;
Dianne Hackborn287952c2010-09-22 22:34:31 -070013349 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013350 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070013351 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013352 }
13353 }
13354 }
13355 }
13356
13357 app.curRawAdj = adj;
13358
Joe Onorato8a9b2202010-02-26 18:56:32 -080013359 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013360 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
13361 if (adj > app.maxAdj) {
13362 adj = app.maxAdj;
Dianne Hackborn7d608422011-08-07 16:24:18 -070013363 if (app.maxAdj <= ProcessList.PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013364 schedGroup = Process.THREAD_GROUP_DEFAULT;
13365 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013366 }
Dianne Hackborn7d608422011-08-07 16:24:18 -070013367 if (adj < ProcessList.HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070013368 app.keeping = true;
13369 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013370
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013371 if (app.hasAboveClient) {
13372 // If this process has bound to any services with BIND_ABOVE_CLIENT,
13373 // then we need to drop its adjustment to be lower than the service's
13374 // in order to honor the request. We want to drop it by one adjustment
13375 // level... but there is special meaning applied to various levels so
13376 // we will skip some of them.
Dianne Hackborn7d608422011-08-07 16:24:18 -070013377 if (adj < ProcessList.FOREGROUND_APP_ADJ) {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013378 // System process will not get dropped, ever
Dianne Hackborn7d608422011-08-07 16:24:18 -070013379 } else if (adj < ProcessList.VISIBLE_APP_ADJ) {
13380 adj = ProcessList.VISIBLE_APP_ADJ;
13381 } else if (adj < ProcessList.PERCEPTIBLE_APP_ADJ) {
13382 adj = ProcessList.PERCEPTIBLE_APP_ADJ;
13383 } else if (adj < ProcessList.HIDDEN_APP_MIN_ADJ) {
13384 adj = ProcessList.HIDDEN_APP_MIN_ADJ;
13385 } else if (adj < ProcessList.EMPTY_APP_ADJ) {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013386 adj++;
13387 }
13388 }
13389
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013390 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013391 app.curSchedGroup = schedGroup;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013392
13393 if (hadForegroundActivities != app.foregroundActivities) {
Jeff Sharkey287bd832011-05-28 19:36:26 -070013394 mHandler.obtainMessage(DISPATCH_FOREGROUND_ACTIVITIES_CHANGED, app.pid, app.info.uid,
13395 app.foregroundActivities).sendToTarget();
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013396 }
13397
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013398 return app.curRawAdj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013399 }
13400
13401 /**
13402 * Ask a given process to GC right now.
13403 */
13404 final void performAppGcLocked(ProcessRecord app) {
13405 try {
13406 app.lastRequestedGc = SystemClock.uptimeMillis();
13407 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013408 if (app.reportLowMemory) {
13409 app.reportLowMemory = false;
13410 app.thread.scheduleLowMemory();
13411 } else {
13412 app.thread.processInBackground();
13413 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013414 }
13415 } catch (Exception e) {
13416 // whatever.
13417 }
13418 }
13419
13420 /**
13421 * Returns true if things are idle enough to perform GCs.
13422 */
Josh Bartel7f208742010-02-25 11:01:44 -060013423 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013424 return mParallelBroadcasts.size() == 0
13425 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013426 && (mSleeping || (mMainStack.mResumedActivity != null &&
13427 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013428 }
13429
13430 /**
13431 * Perform GCs on all processes that are waiting for it, but only
13432 * if things are idle.
13433 */
13434 final void performAppGcsLocked() {
13435 final int N = mProcessesToGc.size();
13436 if (N <= 0) {
13437 return;
13438 }
Josh Bartel7f208742010-02-25 11:01:44 -060013439 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013440 while (mProcessesToGc.size() > 0) {
13441 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn7d608422011-08-07 16:24:18 -070013442 if (proc.curRawAdj > ProcessList.PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013443 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
13444 <= SystemClock.uptimeMillis()) {
13445 // To avoid spamming the system, we will GC processes one
13446 // at a time, waiting a few seconds between each.
13447 performAppGcLocked(proc);
13448 scheduleAppGcsLocked();
13449 return;
13450 } else {
13451 // It hasn't been long enough since we last GCed this
13452 // process... put it in the list to wait for its time.
13453 addProcessToGcListLocked(proc);
13454 break;
13455 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013456 }
13457 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013458
13459 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013460 }
13461 }
13462
13463 /**
13464 * If all looks good, perform GCs on all processes waiting for them.
13465 */
13466 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060013467 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013468 performAppGcsLocked();
13469 return;
13470 }
13471 // Still not idle, wait some more.
13472 scheduleAppGcsLocked();
13473 }
13474
13475 /**
13476 * Schedule the execution of all pending app GCs.
13477 */
13478 final void scheduleAppGcsLocked() {
13479 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013480
13481 if (mProcessesToGc.size() > 0) {
13482 // Schedule a GC for the time to the next process.
13483 ProcessRecord proc = mProcessesToGc.get(0);
13484 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
13485
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013486 long when = proc.lastRequestedGc + GC_MIN_INTERVAL;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013487 long now = SystemClock.uptimeMillis();
13488 if (when < (now+GC_TIMEOUT)) {
13489 when = now + GC_TIMEOUT;
13490 }
13491 mHandler.sendMessageAtTime(msg, when);
13492 }
13493 }
13494
13495 /**
13496 * Add a process to the array of processes waiting to be GCed. Keeps the
13497 * list in sorted order by the last GC time. The process can't already be
13498 * on the list.
13499 */
13500 final void addProcessToGcListLocked(ProcessRecord proc) {
13501 boolean added = false;
13502 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
13503 if (mProcessesToGc.get(i).lastRequestedGc <
13504 proc.lastRequestedGc) {
13505 added = true;
13506 mProcessesToGc.add(i+1, proc);
13507 break;
13508 }
13509 }
13510 if (!added) {
13511 mProcessesToGc.add(0, proc);
13512 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013513 }
13514
13515 /**
13516 * Set up to ask a process to GC itself. This will either do it
13517 * immediately, or put it on the list of processes to gc the next
13518 * time things are idle.
13519 */
13520 final void scheduleAppGcLocked(ProcessRecord app) {
13521 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013522 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013523 return;
13524 }
13525 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013526 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013527 scheduleAppGcsLocked();
13528 }
13529 }
13530
Dianne Hackborn287952c2010-09-22 22:34:31 -070013531 final void checkExcessivePowerUsageLocked(boolean doKills) {
13532 updateCpuStatsNow();
13533
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013534 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
Dianne Hackborn287952c2010-09-22 22:34:31 -070013535 boolean doWakeKills = doKills;
13536 boolean doCpuKills = doKills;
13537 if (mLastPowerCheckRealtime == 0) {
13538 doWakeKills = false;
13539 }
13540 if (mLastPowerCheckUptime == 0) {
13541 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013542 }
13543 if (stats.isScreenOn()) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070013544 doWakeKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013545 }
13546 final long curRealtime = SystemClock.elapsedRealtime();
Dianne Hackborn287952c2010-09-22 22:34:31 -070013547 final long realtimeSince = curRealtime - mLastPowerCheckRealtime;
13548 final long curUptime = SystemClock.uptimeMillis();
13549 final long uptimeSince = curUptime - mLastPowerCheckUptime;
13550 mLastPowerCheckRealtime = curRealtime;
13551 mLastPowerCheckUptime = curUptime;
13552 if (realtimeSince < WAKE_LOCK_MIN_CHECK_DURATION) {
13553 doWakeKills = false;
13554 }
13555 if (uptimeSince < CPU_MIN_CHECK_DURATION) {
13556 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013557 }
13558 int i = mLruProcesses.size();
13559 while (i > 0) {
13560 i--;
13561 ProcessRecord app = mLruProcesses.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -070013562 if (!app.keeping) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013563 long wtime;
13564 synchronized (stats) {
13565 wtime = stats.getProcessWakeTime(app.info.uid,
13566 app.pid, curRealtime);
13567 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070013568 long wtimeUsed = wtime - app.lastWakeTime;
13569 long cputimeUsed = app.curCpuTime - app.lastCpuTime;
13570 if (DEBUG_POWER) {
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070013571 StringBuilder sb = new StringBuilder(128);
13572 sb.append("Wake for ");
13573 app.toShortString(sb);
13574 sb.append(": over ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070013575 TimeUtils.formatDuration(realtimeSince, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070013576 sb.append(" used ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070013577 TimeUtils.formatDuration(wtimeUsed, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070013578 sb.append(" (");
Dianne Hackborn287952c2010-09-22 22:34:31 -070013579 sb.append((wtimeUsed*100)/realtimeSince);
13580 sb.append("%)");
13581 Slog.i(TAG, sb.toString());
13582 sb.setLength(0);
13583 sb.append("CPU for ");
13584 app.toShortString(sb);
13585 sb.append(": over ");
13586 TimeUtils.formatDuration(uptimeSince, sb);
13587 sb.append(" used ");
13588 TimeUtils.formatDuration(cputimeUsed, sb);
13589 sb.append(" (");
13590 sb.append((cputimeUsed*100)/uptimeSince);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070013591 sb.append("%)");
13592 Slog.i(TAG, sb.toString());
13593 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013594 // If a process has held a wake lock for more
13595 // than 50% of the time during this period,
13596 // that sounds pad. Kill!
Dianne Hackborn287952c2010-09-22 22:34:31 -070013597 if (doWakeKills && realtimeSince > 0
13598 && ((wtimeUsed*100)/realtimeSince) >= 50) {
13599 synchronized (stats) {
13600 stats.reportExcessiveWakeLocked(app.info.uid, app.processName,
13601 realtimeSince, wtimeUsed);
13602 }
13603 Slog.w(TAG, "Excessive wake lock in " + app.processName
13604 + " (pid " + app.pid + "): held " + wtimeUsed
13605 + " during " + realtimeSince);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013606 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13607 app.processName, app.setAdj, "excessive wake lock");
13608 Process.killProcessQuiet(app.pid);
Dianne Hackborn287952c2010-09-22 22:34:31 -070013609 } else if (doCpuKills && uptimeSince > 0
13610 && ((cputimeUsed*100)/uptimeSince) >= 50) {
13611 synchronized (stats) {
13612 stats.reportExcessiveCpuLocked(app.info.uid, app.processName,
13613 uptimeSince, cputimeUsed);
13614 }
13615 Slog.w(TAG, "Excessive CPU in " + app.processName
13616 + " (pid " + app.pid + "): used " + cputimeUsed
13617 + " during " + uptimeSince);
13618 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13619 app.processName, app.setAdj, "excessive cpu");
13620 Process.killProcessQuiet(app.pid);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013621 } else {
13622 app.lastWakeTime = wtime;
Dianne Hackborn287952c2010-09-22 22:34:31 -070013623 app.lastCpuTime = app.curCpuTime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013624 }
13625 }
13626 }
13627 }
13628
Dianne Hackborn295e3c22011-08-25 13:19:08 -070013629 private final boolean updateOomAdjLocked(
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013630 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013631 app.hiddenAdj = hiddenAdj;
13632
13633 if (app.thread == null) {
Dianne Hackborn295e3c22011-08-25 13:19:08 -070013634 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013635 }
13636
Dianne Hackborn287952c2010-09-22 22:34:31 -070013637 final boolean wasKeeping = app.keeping;
13638
Dianne Hackborn295e3c22011-08-25 13:19:08 -070013639 boolean success = true;
13640
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013641 computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013642
Jeff Brown10e89712011-07-08 18:52:57 -070013643 if (app.curRawAdj != app.setRawAdj) {
Dianne Hackborn905577f2011-09-07 18:31:28 -070013644 if (false) {
13645 // Removing for now. Forcing GCs is not so useful anymore
13646 // with Dalvik, and the new memory level hint facility is
13647 // better for what we need to do these days.
13648 if (app.curRawAdj > ProcessList.FOREGROUND_APP_ADJ
13649 && app.setRawAdj <= ProcessList.FOREGROUND_APP_ADJ) {
13650 // If this app is transitioning from foreground to
13651 // non-foreground, have it do a gc.
13652 scheduleAppGcLocked(app);
13653 } else if (app.curRawAdj >= ProcessList.HIDDEN_APP_MIN_ADJ
13654 && app.setRawAdj < ProcessList.HIDDEN_APP_MIN_ADJ) {
13655 // Likewise do a gc when an app is moving in to the
13656 // background (such as a service stopping).
13657 scheduleAppGcLocked(app);
13658 }
Jeff Brown10e89712011-07-08 18:52:57 -070013659 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070013660
Jeff Brown10e89712011-07-08 18:52:57 -070013661 if (wasKeeping && !app.keeping) {
13662 // This app is no longer something we want to keep. Note
13663 // its current wake lock time to later know to kill it if
13664 // it is not behaving well.
13665 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
13666 synchronized (stats) {
13667 app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
13668 app.pid, SystemClock.elapsedRealtime());
13669 }
13670 app.lastCpuTime = app.curCpuTime;
13671 }
13672
13673 app.setRawAdj = app.curRawAdj;
13674 }
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013675 if (app.curAdj != app.setAdj) {
13676 if (Process.setOomAdj(app.pid, app.curAdj)) {
Jeff Brown10e89712011-07-08 18:52:57 -070013677 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
13678 TAG, "Set app " + app.processName +
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013679 " oom adj to " + app.curAdj + " because " + app.adjType);
13680 app.setAdj = app.curAdj;
Jeff Brown10e89712011-07-08 18:52:57 -070013681 } else {
Dianne Hackborn295e3c22011-08-25 13:19:08 -070013682 success = false;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013683 Slog.w(TAG, "Failed setting oom adj of " + app + " to " + app.curAdj);
Jeff Brown10e89712011-07-08 18:52:57 -070013684 }
13685 }
13686 if (app.setSchedGroup != app.curSchedGroup) {
13687 app.setSchedGroup = app.curSchedGroup;
13688 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
13689 "Setting process group of " + app.processName
13690 + " to " + app.curSchedGroup);
13691 if (app.waitingToKill != null &&
13692 app.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {
13693 Slog.i(TAG, "Killing " + app.toShortString() + ": " + app.waitingToKill);
13694 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13695 app.processName, app.setAdj, app.waitingToKill);
13696 Process.killProcessQuiet(app.pid);
Dianne Hackborn295e3c22011-08-25 13:19:08 -070013697 success = false;
Jeff Brown10e89712011-07-08 18:52:57 -070013698 } else {
13699 if (true) {
13700 long oldId = Binder.clearCallingIdentity();
13701 try {
13702 Process.setProcessGroup(app.pid, app.curSchedGroup);
13703 } catch (Exception e) {
13704 Slog.w(TAG, "Failed setting process group of " + app.pid
13705 + " to " + app.curSchedGroup);
13706 e.printStackTrace();
13707 } finally {
13708 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070013709 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013710 } else {
Jeff Brown10e89712011-07-08 18:52:57 -070013711 if (app.thread != null) {
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013712 try {
Jeff Brown10e89712011-07-08 18:52:57 -070013713 app.thread.setSchedulingGroup(app.curSchedGroup);
13714 } catch (RemoteException e) {
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070013715 }
13716 }
13717 }
13718 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013719 }
Dianne Hackborn295e3c22011-08-25 13:19:08 -070013720 return success;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013721 }
13722
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013723 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013724 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013725 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013726 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013727 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013728 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013729 }
13730 }
13731 return resumedActivity;
13732 }
13733
Dianne Hackborn295e3c22011-08-25 13:19:08 -070013734 private final boolean updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013735 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013736 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
13737 int curAdj = app.curAdj;
Dianne Hackborn7d608422011-08-07 16:24:18 -070013738 final boolean wasHidden = curAdj >= ProcessList.HIDDEN_APP_MIN_ADJ
13739 && curAdj <= ProcessList.HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013740
13741 mAdjSeq++;
13742
Dianne Hackborn295e3c22011-08-25 13:19:08 -070013743 boolean success = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
Dianne Hackborn7d608422011-08-07 16:24:18 -070013744 final boolean nowHidden = app.curAdj >= ProcessList.HIDDEN_APP_MIN_ADJ
13745 && app.curAdj <= ProcessList.HIDDEN_APP_MAX_ADJ;
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013746 if (nowHidden != wasHidden) {
13747 // Changed to/from hidden state, so apps after it in the LRU
13748 // list may also be changed.
13749 updateOomAdjLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013750 }
Dianne Hackborn295e3c22011-08-25 13:19:08 -070013751 return success;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013752 }
13753
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013754 final void updateOomAdjLocked() {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013755 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013756 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
13757
13758 if (false) {
13759 RuntimeException e = new RuntimeException();
13760 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080013761 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013762 }
13763
13764 mAdjSeq++;
13765
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013766 // Let's determine how many processes we have running vs.
13767 // how many slots we have for background processes; we may want
13768 // to put multiple processes in a slot of there are enough of
13769 // them.
Dianne Hackborn7d608422011-08-07 16:24:18 -070013770 int numSlots = ProcessList.HIDDEN_APP_MAX_ADJ - ProcessList.HIDDEN_APP_MIN_ADJ + 1;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013771 int factor = (mLruProcesses.size()-4)/numSlots;
13772 if (factor < 1) factor = 1;
13773 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070013774 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013775
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013776 // First update the OOM adjustment for each of the
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013777 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013778 int i = mLruProcesses.size();
Dianne Hackborn7d608422011-08-07 16:24:18 -070013779 int curHiddenAdj = ProcessList.HIDDEN_APP_MIN_ADJ;
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013780 int numBg = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013781 while (i > 0) {
13782 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013783 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013784 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013785 updateOomAdjLocked(app, curHiddenAdj, TOP_APP);
Dianne Hackborn7d608422011-08-07 16:24:18 -070013786 if (curHiddenAdj < ProcessList.EMPTY_APP_ADJ
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013787 && app.curAdj == curHiddenAdj) {
13788 step++;
13789 if (step >= factor) {
13790 step = 0;
13791 curHiddenAdj++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013792 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013793 }
13794 if (!app.killedBackground) {
Dianne Hackborn7d608422011-08-07 16:24:18 -070013795 if (app.curAdj >= ProcessList.HIDDEN_APP_MIN_ADJ) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013796 numHidden++;
13797 if (numHidden > mProcessLimit) {
13798 Slog.i(TAG, "No longer want " + app.processName
13799 + " (pid " + app.pid + "): hidden #" + numHidden);
13800 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13801 app.processName, app.setAdj, "too many background");
13802 app.killedBackground = true;
13803 Process.killProcessQuiet(app.pid);
13804 } else {
13805 numBg++;
Dianne Hackborn8633e682010-04-22 16:03:41 -070013806 }
Dianne Hackborn7d608422011-08-07 16:24:18 -070013807 } else if (app.curAdj >= ProcessList.HOME_APP_ADJ) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013808 numBg++;
Dianne Hackborn8633e682010-04-22 16:03:41 -070013809 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013810 }
13811 }
13812
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013813 // Now determine the memory trimming level of background processes.
13814 // Unfortunately we need to start at the back of the list to do this
13815 // properly. We only do this if the number of background apps we
13816 // are managing to keep around is less than half the maximum we desire;
13817 // if we are keeping a good number around, we'll let them use whatever
13818 // memory they want.
Dianne Hackborn7d608422011-08-07 16:24:18 -070013819 if (numHidden <= (ProcessList.MAX_HIDDEN_APPS/2)) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013820 final int N = mLruProcesses.size();
13821 factor = numBg/3;
13822 step = 0;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013823 int curLevel = ComponentCallbacks2.TRIM_MEMORY_COMPLETE;
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013824 for (i=0; i<N; i++) {
13825 ProcessRecord app = mLruProcesses.get(i);
Dianne Hackborn7d608422011-08-07 16:24:18 -070013826 if (app.curAdj >= ProcessList.HIDDEN_APP_MIN_ADJ && !app.killedBackground) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013827 if (app.trimMemoryLevel < curLevel && app.thread != null) {
13828 try {
13829 app.thread.scheduleTrimMemory(curLevel);
13830 } catch (RemoteException e) {
13831 }
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013832 if (curLevel >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013833 // For these apps we will also finish their activities
13834 // to help them free memory.
13835 mMainStack.destroyActivitiesLocked(app, false);
13836 }
13837 }
13838 app.trimMemoryLevel = curLevel;
13839 step++;
13840 if (step >= factor) {
13841 switch (curLevel) {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013842 case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:
13843 curLevel = ComponentCallbacks2.TRIM_MEMORY_MODERATE;
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013844 break;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013845 case ComponentCallbacks2.TRIM_MEMORY_MODERATE:
13846 curLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013847 break;
13848 }
13849 }
Dianne Hackborn7d608422011-08-07 16:24:18 -070013850 } else if (app.curAdj == ProcessList.HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013851 if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_BACKGROUND
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013852 && app.thread != null) {
13853 try {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013854 app.thread.scheduleTrimMemory(
13855 ComponentCallbacks2.TRIM_MEMORY_BACKGROUND);
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013856 } catch (RemoteException e) {
13857 }
13858 }
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013859 app.trimMemoryLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
Dianne Hackborn7d608422011-08-07 16:24:18 -070013860 } else if ((app.curAdj > ProcessList.VISIBLE_APP_ADJ || app.systemNoUi)
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013861 && app.pendingUiClean) {
13862 if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN
13863 && app.thread != null) {
13864 try {
13865 app.thread.scheduleTrimMemory(
13866 ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
13867 } catch (RemoteException e) {
13868 }
13869 }
13870 app.trimMemoryLevel = ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN;
13871 app.pendingUiClean = false;
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013872 } else {
13873 app.trimMemoryLevel = 0;
13874 }
13875 }
13876 } else {
13877 final int N = mLruProcesses.size();
13878 for (i=0; i<N; i++) {
13879 ProcessRecord app = mLruProcesses.get(i);
Dianne Hackborn7d608422011-08-07 16:24:18 -070013880 if ((app.curAdj > ProcessList.VISIBLE_APP_ADJ || app.systemNoUi)
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013881 && app.pendingUiClean) {
13882 if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN
13883 && app.thread != null) {
13884 try {
13885 app.thread.scheduleTrimMemory(
13886 ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
13887 } catch (RemoteException e) {
13888 }
13889 }
13890 app.trimMemoryLevel = ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN;
13891 app.pendingUiClean = false;
13892 } else {
13893 app.trimMemoryLevel = 0;
13894 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013895 }
13896 }
13897
13898 if (mAlwaysFinishActivities) {
13899 mMainStack.destroyActivitiesLocked(null, false);
13900 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013901 }
13902
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013903 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013904 synchronized (this) {
13905 int i;
13906
13907 // First remove any unused application processes whose package
13908 // has been removed.
13909 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
13910 final ProcessRecord app = mRemovedProcesses.get(i);
13911 if (app.activities.size() == 0
13912 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013913 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013914 TAG, "Exiting empty application process "
13915 + app.processName + " ("
13916 + (app.thread != null ? app.thread.asBinder() : null)
13917 + ")\n");
13918 if (app.pid > 0 && app.pid != MY_PID) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070013919 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
13920 app.processName, app.setAdj, "empty");
13921 Process.killProcessQuiet(app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013922 } else {
13923 try {
13924 app.thread.scheduleExit();
13925 } catch (Exception e) {
13926 // Ignore exceptions.
13927 }
13928 }
Dianne Hackborn130b0d22011-07-26 22:07:48 -070013929 cleanUpApplicationRecordLocked(app, false, true, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013930 mRemovedProcesses.remove(i);
13931
13932 if (app.persistent) {
13933 if (app.persistent) {
13934 addAppLocked(app.info);
13935 }
13936 }
13937 }
13938 }
13939
Dianne Hackbornce86ba82011-07-13 19:33:41 -070013940 // Now update the oom adj for all processes.
13941 updateOomAdjLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013942 }
13943 }
13944
13945 /** This method sends the specified signal to each of the persistent apps */
13946 public void signalPersistentProcesses(int sig) throws RemoteException {
13947 if (sig != Process.SIGNAL_USR1) {
13948 throw new SecurityException("Only SIGNAL_USR1 is allowed");
13949 }
13950
13951 synchronized (this) {
13952 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
13953 != PackageManager.PERMISSION_GRANTED) {
13954 throw new SecurityException("Requires permission "
13955 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
13956 }
13957
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013958 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
13959 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013960 if (r.thread != null && r.persistent) {
13961 Process.sendSignal(r.pid, sig);
13962 }
13963 }
13964 }
13965 }
13966
Dianne Hackborn62f20ec2011-08-15 17:40:28 -070013967 private void stopProfilerLocked(ProcessRecord proc, String path, int profileType) {
13968 if (proc == null || proc == mProfileProc) {
13969 proc = mProfileProc;
13970 path = mProfileFile;
13971 profileType = mProfileType;
13972 clearProfilerLocked();
13973 }
13974 if (proc == null) {
13975 return;
13976 }
13977 try {
13978 proc.thread.profilerControl(false, path, null, profileType);
13979 } catch (RemoteException e) {
13980 throw new IllegalStateException("Process disappeared");
13981 }
13982 }
13983
13984 private void clearProfilerLocked() {
13985 if (mProfileFd != null) {
13986 try {
13987 mProfileFd.close();
13988 } catch (IOException e) {
13989 }
13990 }
13991 mProfileApp = null;
13992 mProfileProc = null;
13993 mProfileFile = null;
13994 mProfileType = 0;
13995 mAutoStopProfiler = false;
13996 }
13997
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080013998 public boolean profileControl(String process, boolean start,
Romain Guy7eabe552011-07-21 14:56:34 -070013999 String path, ParcelFileDescriptor fd, int profileType) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014000
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014001 try {
14002 synchronized (this) {
14003 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
14004 // its own permission.
14005 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
14006 != PackageManager.PERMISSION_GRANTED) {
14007 throw new SecurityException("Requires permission "
14008 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014009 }
Dianne Hackborn62f20ec2011-08-15 17:40:28 -070014010
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014011 if (start && fd == null) {
14012 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014013 }
Dianne Hackborn62f20ec2011-08-15 17:40:28 -070014014
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014015 ProcessRecord proc = null;
Dianne Hackborn62f20ec2011-08-15 17:40:28 -070014016 if (process != null) {
14017 try {
14018 int pid = Integer.parseInt(process);
14019 synchronized (mPidsSelfLocked) {
14020 proc = mPidsSelfLocked.get(pid);
14021 }
14022 } catch (NumberFormatException e) {
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014023 }
Dianne Hackborn62f20ec2011-08-15 17:40:28 -070014024
14025 if (proc == null) {
14026 HashMap<String, SparseArray<ProcessRecord>> all
14027 = mProcessNames.getMap();
14028 SparseArray<ProcessRecord> procs = all.get(process);
14029 if (procs != null && procs.size() > 0) {
14030 proc = procs.valueAt(0);
14031 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014032 }
14033 }
Dianne Hackborn62f20ec2011-08-15 17:40:28 -070014034
14035 if (start && (proc == null || proc.thread == null)) {
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014036 throw new IllegalArgumentException("Unknown process: " + process);
14037 }
Dianne Hackborn62f20ec2011-08-15 17:40:28 -070014038
14039 if (start) {
14040 stopProfilerLocked(null, null, 0);
14041 setProfileApp(proc.info, proc.processName, path, fd, false);
14042 mProfileProc = proc;
14043 mProfileType = profileType;
14044 try {
14045 fd = fd.dup();
14046 } catch (IOException e) {
14047 fd = null;
14048 }
14049 proc.thread.profilerControl(start, path, fd, profileType);
14050 fd = null;
14051 mProfileFd = null;
14052 } else {
14053 stopProfilerLocked(proc, path, profileType);
14054 if (fd != null) {
14055 try {
14056 fd.close();
14057 } catch (IOException e) {
14058 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014059 }
14060 }
Dianne Hackborn62f20ec2011-08-15 17:40:28 -070014061
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014062 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014063 }
14064 } catch (RemoteException e) {
14065 throw new IllegalStateException("Process disappeared");
14066 } finally {
14067 if (fd != null) {
14068 try {
14069 fd.close();
14070 } catch (IOException e) {
14071 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014072 }
14073 }
14074 }
Andy McFadden824c5102010-07-09 16:26:57 -070014075
14076 public boolean dumpHeap(String process, boolean managed,
14077 String path, ParcelFileDescriptor fd) throws RemoteException {
14078
14079 try {
14080 synchronized (this) {
14081 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
14082 // its own permission (same as profileControl).
14083 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
14084 != PackageManager.PERMISSION_GRANTED) {
14085 throw new SecurityException("Requires permission "
14086 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
14087 }
14088
14089 if (fd == null) {
14090 throw new IllegalArgumentException("null fd");
14091 }
14092
14093 ProcessRecord proc = null;
14094 try {
14095 int pid = Integer.parseInt(process);
14096 synchronized (mPidsSelfLocked) {
14097 proc = mPidsSelfLocked.get(pid);
14098 }
14099 } catch (NumberFormatException e) {
14100 }
14101
14102 if (proc == null) {
14103 HashMap<String, SparseArray<ProcessRecord>> all
14104 = mProcessNames.getMap();
14105 SparseArray<ProcessRecord> procs = all.get(process);
14106 if (procs != null && procs.size() > 0) {
14107 proc = procs.valueAt(0);
14108 }
14109 }
14110
14111 if (proc == null || proc.thread == null) {
14112 throw new IllegalArgumentException("Unknown process: " + process);
14113 }
14114
Dianne Hackbornf02e57b2011-03-01 22:21:04 -080014115 boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
14116 if (!isDebuggable) {
Andy McFadden824c5102010-07-09 16:26:57 -070014117 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
14118 throw new SecurityException("Process not debuggable: " + proc);
14119 }
14120 }
14121
14122 proc.thread.dumpHeap(managed, path, fd);
14123 fd = null;
14124 return true;
14125 }
14126 } catch (RemoteException e) {
14127 throw new IllegalStateException("Process disappeared");
14128 } finally {
14129 if (fd != null) {
14130 try {
14131 fd.close();
14132 } catch (IOException e) {
14133 }
14134 }
14135 }
14136 }
14137
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014138 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
14139 public void monitor() {
14140 synchronized (this) { }
14141 }
Svetoslav Ganov54d068e2011-03-02 12:58:40 -080014142
14143 public void onCoreSettingsChange(Bundle settings) {
14144 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
14145 ProcessRecord processRecord = mLruProcesses.get(i);
14146 try {
14147 if (processRecord.thread != null) {
14148 processRecord.thread.setCoreSettings(settings);
14149 }
14150 } catch (RemoteException re) {
14151 /* ignore */
14152 }
14153 }
14154 }
Amith Yamasani4b2e9342011-03-31 12:38:53 -070014155
14156 // Multi-user methods
14157
14158 public boolean switchUser(int userid) {
14159 // TODO
14160 return true;
14161 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014162}