blob: bbb4917fbab24f1637b08dc203bd960b5ee78492 [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;
Dianne Hackborn04d6db32011-11-04 20:07:24 -0700123import java.io.BufferedReader;
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700124import java.io.DataInputStream;
125import java.io.DataOutputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800126import java.io.File;
127import java.io.FileDescriptor;
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700128import java.io.FileInputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800129import java.io.FileNotFoundException;
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700130import java.io.FileOutputStream;
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200131import java.io.IOException;
Dan Egnora455d192010-03-12 08:52:28 -0800132import java.io.InputStreamReader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800133import java.io.PrintWriter;
Dianne Hackborn04d6db32011-11-04 20:07:24 -0700134import java.io.StringWriter;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800135import java.lang.IllegalStateException;
136import java.lang.ref.WeakReference;
137import java.util.ArrayList;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700138import java.util.Collections;
139import java.util.Comparator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800140import java.util.HashMap;
141import java.util.HashSet;
142import java.util.Iterator;
143import java.util.List;
144import java.util.Locale;
145import java.util.Map;
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -0700146import java.util.Set;
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700147import java.util.concurrent.atomic.AtomicBoolean;
148import java.util.concurrent.atomic.AtomicLong;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800149
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700150public final class ActivityManagerService extends ActivityManagerNative
151 implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800152 static final String TAG = "ActivityManager";
153 static final boolean DEBUG = false;
Dianne Hackborne2515ee2011-04-27 18:52:56 -0400154 static final boolean localLOGV = DEBUG;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800155 static final boolean DEBUG_SWITCH = localLOGV || false;
156 static final boolean DEBUG_TASKS = localLOGV || false;
157 static final boolean DEBUG_PAUSE = localLOGV || false;
158 static final boolean DEBUG_OOM_ADJ = localLOGV || false;
159 static final boolean DEBUG_TRANSITION = localLOGV || false;
160 static final boolean DEBUG_BROADCAST = localLOGV || false;
Dianne Hackborn82f3f002009-06-16 18:49:05 -0700161 static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800162 static final boolean DEBUG_SERVICE = localLOGV || false;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700163 static final boolean DEBUG_SERVICE_EXECUTING = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800164 static final boolean DEBUG_VISBILITY = localLOGV || false;
165 static final boolean DEBUG_PROCESSES = localLOGV || false;
Dianne Hackborna1e989b2009-09-01 19:54:29 -0700166 static final boolean DEBUG_PROVIDER = localLOGV || false;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800167 static final boolean DEBUG_URI_PERMISSION = localLOGV || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800168 static final boolean DEBUG_USER_LEAVING = localLOGV || false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700169 static final boolean DEBUG_RESULTS = localLOGV || false;
Dianne Hackborn98cfebc2011-10-18 13:17:33 -0700170 static final boolean DEBUG_BACKUP = localLOGV || false;
Dianne Hackborndc6b6352009-09-30 14:20:09 -0700171 static final boolean DEBUG_CONFIGURATION = localLOGV || false;
Dianne Hackborn287952c2010-09-22 22:34:31 -0700172 static final boolean DEBUG_POWER = localLOGV || false;
173 static final boolean DEBUG_POWER_QUICK = DEBUG_POWER || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800174 static final boolean VALIDATE_TOKENS = false;
175 static final boolean SHOW_ACTIVITY_START_TIME = true;
176
177 // Control over CPU and battery monitoring.
178 static final long BATTERY_STATS_TIME = 30*60*1000; // write battery stats every 30 minutes.
179 static final boolean MONITOR_CPU_USAGE = true;
180 static final long MONITOR_CPU_MIN_TIME = 5*1000; // don't sample cpu less than every 5 seconds.
181 static final long MONITOR_CPU_MAX_TIME = 0x0fffffff; // wait possibly forever for next cpu sample.
182 static final boolean MONITOR_THREAD_CPU_USAGE = false;
183
Dianne Hackborn1655be42009-05-08 14:29:01 -0700184 // The flags that are set for all calls we make to the package manager.
Dianne Hackborn11b822d2009-07-21 20:03:02 -0700185 static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES;
Dianne Hackborn1655be42009-05-08 14:29:01 -0700186
Dianne Hackbornf02e57b2011-03-01 22:21:04 -0800187 private static final String SYSTEM_DEBUGGABLE = "ro.debuggable";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800188
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800189 // Maximum number of recent tasks that we can remember.
190 static final int MAX_RECENT_TASKS = 20;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700191
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700192 // Amount of time after a call to stopAppSwitches() during which we will
193 // prevent further untrusted switches from happening.
194 static final long APP_SWITCH_DELAY_TIME = 5*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800195
196 // How long we wait for a launched process to attach to the activity manager
197 // before we decide it's never going to come up for real.
198 static final int PROC_START_TIMEOUT = 10*1000;
199
Jeff Brown3f9dd282011-07-08 20:02:19 -0700200 // How long we wait for a launched process to attach to the activity manager
201 // before we decide it's never going to come up for real, when the process was
202 // started with a wrapper for instrumentation (such as Valgrind) because it
203 // could take much longer than usual.
204 static final int PROC_START_TIMEOUT_WITH_WRAPPER = 300*1000;
205
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800206 // How long to wait after going idle before forcing apps to GC.
207 static final int GC_TIMEOUT = 5*1000;
208
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700209 // The minimum amount of time between successive GC requests for a process.
210 static final int GC_MIN_INTERVAL = 60*1000;
211
Dianne Hackborn287952c2010-09-22 22:34:31 -0700212 // The rate at which we check for apps using excessive power -- 15 mins.
213 static final int POWER_CHECK_DELAY = (DEBUG_POWER_QUICK ? 2 : 15) * 60*1000;
214
215 // The minimum sample duration we will allow before deciding we have
216 // enough data on wake locks to start killing things.
217 static final int WAKE_LOCK_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
218
219 // The minimum sample duration we will allow before deciding we have
220 // enough data on CPU usage to start killing things.
221 static final int CPU_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700222
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800223 // How long we allow a receiver to run before giving up on it.
224 static final int BROADCAST_TIMEOUT = 10*1000;
225
226 // How long we wait for a service to finish executing.
227 static final int SERVICE_TIMEOUT = 20*1000;
228
229 // How long a service needs to be running until restarting its process
230 // is no longer considered to be a relaunch of the service.
231 static final int SERVICE_RESTART_DURATION = 5*1000;
232
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700233 // How long a service needs to be running until it will start back at
234 // SERVICE_RESTART_DURATION after being killed.
235 static final int SERVICE_RESET_RUN_DURATION = 60*1000;
236
237 // Multiplying factor to increase restart duration time by, for each time
238 // a service is killed before it has run for SERVICE_RESET_RUN_DURATION.
239 static final int SERVICE_RESTART_DURATION_FACTOR = 4;
240
241 // The minimum amount of time between restarting services that we allow.
242 // That is, when multiple services are restarting, we won't allow each
243 // to restart less than this amount of time from the last one.
244 static final int SERVICE_MIN_RESTART_TIME_BETWEEN = 10*1000;
245
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800246 // Maximum amount of time for there to be no activity on a service before
247 // we consider it non-essential and allow its process to go on the
248 // LRU background list.
Dianne Hackbornfd12af42009-08-27 00:44:33 -0700249 static final int MAX_SERVICE_INACTIVITY = 30*60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800250
251 // How long we wait until we timeout on key dispatching.
252 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
253
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800254 // How long we wait until we timeout on key dispatching during instrumentation.
255 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000;
256
Dan Egnor42471dd2010-01-07 17:25:22 -0800257 static final int MY_PID = Process.myPid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800258
259 static final String[] EMPTY_STRING_ARRAY = new String[0];
260
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700261 public ActivityStack mMainStack;
262
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800263 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700264 * Description of a request to start a new activity, which has been held
265 * due to app switches being disabled.
266 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700267 static class PendingActivityLaunch {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700268 ActivityRecord r;
269 ActivityRecord sourceRecord;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700270 Uri[] grantedUriPermissions;
271 int grantedMode;
272 boolean onlyIfNeeded;
273 }
274
275 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches
276 = new ArrayList<PendingActivityLaunch>();
277
278 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800279 * List of all active broadcasts that are to be executed immediately
280 * (without waiting for another broadcast to finish). Currently this only
281 * contains broadcasts to registered receivers, to avoid spinning up
282 * a bunch of processes to execute IntentReceiver components.
283 */
284 final ArrayList<BroadcastRecord> mParallelBroadcasts
285 = new ArrayList<BroadcastRecord>();
286
287 /**
288 * List of all active broadcasts that are to be executed one at a time.
289 * The object at the top of the list is the currently activity broadcasts;
290 * those after it are waiting for the top to finish..
291 */
292 final ArrayList<BroadcastRecord> mOrderedBroadcasts
293 = new ArrayList<BroadcastRecord>();
294
295 /**
Dianne Hackborn12527f92009-11-11 17:39:50 -0800296 * Historical data of past broadcasts, for debugging.
297 */
Dianne Hackborn28695e02011-11-02 21:59:51 -0700298 static final int MAX_BROADCAST_HISTORY = 25;
Dianne Hackborn12527f92009-11-11 17:39:50 -0800299 final BroadcastRecord[] mBroadcastHistory
300 = new BroadcastRecord[MAX_BROADCAST_HISTORY];
301
302 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800303 * Set when we current have a BROADCAST_INTENT_MSG in flight.
304 */
305 boolean mBroadcastsScheduled = false;
306
307 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800308 * Activity we have told the window manager to have key focus.
309 */
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700310 ActivityRecord mFocusedActivity = null;
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700311 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800312 * List of intents that were used to start the most recent tasks.
313 */
Dianne Hackborn0c5001d2011-04-12 18:16:08 -0700314 final ArrayList<TaskRecord> mRecentTasks = new ArrayList<TaskRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800315
316 /**
Dianne Hackborn7d608422011-08-07 16:24:18 -0700317 * Process management.
318 */
319 final ProcessList mProcessList = new ProcessList();
320
321 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800322 * All of the applications we currently have running organized by name.
323 * The keys are strings of the application package name (as
324 * returned by the package manager), and the keys are ApplicationRecord
325 * objects.
326 */
Dianne Hackborn0c5001d2011-04-12 18:16:08 -0700327 final ProcessMap<ProcessRecord> mProcessNames = new ProcessMap<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800328
329 /**
Dianne Hackborn860755f2010-06-03 18:47:52 -0700330 * The currently running heavy-weight process, if any.
331 */
332 ProcessRecord mHeavyWeightProcess = null;
333
334 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800335 * The last time that various processes have crashed.
336 */
337 final ProcessMap<Long> mProcessCrashTimes = new ProcessMap<Long>();
338
339 /**
340 * Set of applications that we consider to be bad, and will reject
341 * incoming broadcasts from (which the user has no control over).
342 * Processes are added to this set when they have crashed twice within
343 * a minimum amount of time; they are removed from it when they are
344 * later restarted (hopefully due to some user action). The value is the
345 * time it was added to the list.
346 */
347 final ProcessMap<Long> mBadProcesses = new ProcessMap<Long>();
348
349 /**
350 * All of the processes we currently have running organized by pid.
351 * The keys are the pid running the application.
352 *
353 * <p>NOTE: This object is protected by its own lock, NOT the global
354 * activity manager lock!
355 */
Dianne Hackborn0c5001d2011-04-12 18:16:08 -0700356 final SparseArray<ProcessRecord> mPidsSelfLocked = new SparseArray<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800357
358 /**
359 * All of the processes that have been forced to be foreground. The key
360 * is the pid of the caller who requested it (we hold a death
361 * link on it).
362 */
363 abstract class ForegroundToken implements IBinder.DeathRecipient {
364 int pid;
365 IBinder token;
366 }
367 final SparseArray<ForegroundToken> mForegroundProcesses
368 = new SparseArray<ForegroundToken>();
369
370 /**
371 * List of records for processes that someone had tried to start before the
372 * system was ready. We don't start them at that point, but ensure they
373 * are started by the time booting is complete.
374 */
375 final ArrayList<ProcessRecord> mProcessesOnHold
376 = new ArrayList<ProcessRecord>();
377
378 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800379 * List of persistent applications that are in the process
380 * of being started.
381 */
382 final ArrayList<ProcessRecord> mPersistentStartingProcesses
383 = new ArrayList<ProcessRecord>();
384
385 /**
386 * Processes that are being forcibly torn down.
387 */
388 final ArrayList<ProcessRecord> mRemovedProcesses
389 = new ArrayList<ProcessRecord>();
390
391 /**
392 * List of running applications, sorted by recent usage.
393 * The first entry in the list is the least recently used.
394 * It contains ApplicationRecord objects. This list does NOT include
395 * any persistent application records (since we never want to exit them).
396 */
Dianne Hackborndd71fc82009-12-16 19:24:32 -0800397 final ArrayList<ProcessRecord> mLruProcesses
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800398 = new ArrayList<ProcessRecord>();
399
400 /**
401 * List of processes that should gc as soon as things are idle.
402 */
403 final ArrayList<ProcessRecord> mProcessesToGc
404 = new ArrayList<ProcessRecord>();
405
406 /**
The Android Open Source Project4df24232009-03-05 14:34:35 -0800407 * This is the process holding what we currently consider to be
408 * the "home" activity.
409 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -0700410 ProcessRecord mHomeProcess;
The Android Open Source Project4df24232009-03-05 14:34:35 -0800411
412 /**
Dianne Hackbornf35fe232011-11-01 19:25:20 -0700413 * This is the process holding the activity the user last visited that
414 * is in a different process from the one they are currently in.
415 */
416 ProcessRecord mPreviousProcess;
Dianne Hackborn50685602011-12-01 12:23:37 -0800417
418 /**
419 * The time at which the previous process was last visible.
420 */
421 long mPreviousProcessVisibleTime;
422
Dianne Hackbornf35fe232011-11-01 19:25:20 -0700423 /**
Dianne Hackborne2515ee2011-04-27 18:52:56 -0400424 * Packages that the user has asked to have run in screen size
425 * compatibility mode instead of filling the screen.
426 */
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -0700427 final CompatModePackages mCompatModePackages;
Dianne Hackborne2515ee2011-04-27 18:52:56 -0400428
429 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800430 * Set of PendingResultRecord objects that are currently active.
431 */
432 final HashSet mPendingResultRecords = new HashSet();
433
434 /**
435 * Set of IntentSenderRecord objects that are currently active.
436 */
437 final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
438 = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
439
440 /**
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -0800441 * Fingerprints (hashCode()) of stack traces that we've
Brad Fitzpatrick143666f2010-06-14 12:40:21 -0700442 * already logged DropBox entries for. Guarded by itself. If
443 * something (rogue user app) forces this over
444 * MAX_DUP_SUPPRESSED_STACKS entries, the contents are cleared.
445 */
446 private final HashSet<Integer> mAlreadyLoggedViolatedStacks = new HashSet<Integer>();
447 private static final int MAX_DUP_SUPPRESSED_STACKS = 5000;
448
449 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -0700450 * Strict Mode background batched logging state.
451 *
452 * The string buffer is guarded by itself, and its lock is also
453 * used to determine if another batched write is already
454 * in-flight.
455 */
456 private final StringBuilder mStrictModeBuffer = new StringBuilder();
457
458 /**
Jeff Brown4d94a762010-09-23 11:33:28 -0700459 * True if we have a pending unexpired BROADCAST_TIMEOUT_MSG posted to our handler.
460 */
461 private boolean mPendingBroadcastTimeoutMessage;
462
463 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800464 * Intent broadcast that we have tried to start, but are
465 * waiting for its application's process to be created. We only
466 * need one (instead of a list) because we always process broadcasts
467 * one at a time, so no others can be started while waiting for this
468 * one.
469 */
470 BroadcastRecord mPendingBroadcast = null;
471
472 /**
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700473 * The receiver index that is pending, to restart the broadcast if needed.
474 */
475 int mPendingBroadcastRecvIndex;
476
477 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800478 * Keeps track of all IIntentReceivers that have been registered for
479 * broadcasts. Hash keys are the receiver IBinder, hash value is
480 * a ReceiverList.
481 */
482 final HashMap mRegisteredReceivers = new HashMap();
483
484 /**
485 * Resolver for broadcast intents to registered receivers.
486 * Holds BroadcastFilter (subclass of IntentFilter).
487 */
488 final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
489 = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
490 @Override
491 protected boolean allowFilterResult(
492 BroadcastFilter filter, List<BroadcastFilter> dest) {
493 IBinder target = filter.receiverList.receiver.asBinder();
494 for (int i=dest.size()-1; i>=0; i--) {
495 if (dest.get(i).receiverList.receiver.asBinder() == target) {
496 return false;
497 }
498 }
499 return true;
500 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -0700501
502 @Override
503 protected String packageForFilter(BroadcastFilter filter) {
504 return filter.packageName;
505 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800506 };
507
508 /**
509 * State of all active sticky broadcasts. Keys are the action of the
510 * sticky Intent, values are an ArrayList of all broadcasted intents with
511 * that action (which should usually be one).
512 */
513 final HashMap<String, ArrayList<Intent>> mStickyBroadcasts =
514 new HashMap<String, ArrayList<Intent>>();
515
516 /**
517 * All currently running services.
518 */
519 final HashMap<ComponentName, ServiceRecord> mServices =
520 new HashMap<ComponentName, ServiceRecord>();
521
522 /**
523 * All currently running services indexed by the Intent used to start them.
524 */
525 final HashMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent =
526 new HashMap<Intent.FilterComparison, ServiceRecord>();
527
528 /**
529 * All currently bound service connections. Keys are the IBinder of
530 * the client's IServiceConnection.
531 */
Dianne Hackborn43d9ac82010-08-25 15:06:25 -0700532 final HashMap<IBinder, ArrayList<ConnectionRecord>> mServiceConnections
533 = new HashMap<IBinder, ArrayList<ConnectionRecord>>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800534
535 /**
536 * List of services that we have been asked to start,
537 * but haven't yet been able to. It is used to hold start requests
538 * while waiting for their corresponding application thread to get
539 * going.
540 */
541 final ArrayList<ServiceRecord> mPendingServices
542 = new ArrayList<ServiceRecord>();
543
544 /**
545 * List of services that are scheduled to restart following a crash.
546 */
547 final ArrayList<ServiceRecord> mRestartingServices
548 = new ArrayList<ServiceRecord>();
549
550 /**
551 * List of services that are in the process of being stopped.
552 */
553 final ArrayList<ServiceRecord> mStoppingServices
554 = new ArrayList<ServiceRecord>();
555
556 /**
Christopher Tate181fafa2009-05-14 11:12:14 -0700557 * Backup/restore process management
558 */
559 String mBackupAppName = null;
560 BackupRecord mBackupTarget = null;
561
562 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800563 * List of PendingThumbnailsRecord objects of clients who are still
564 * waiting to receive all of the thumbnails for a task.
565 */
566 final ArrayList mPendingThumbnails = new ArrayList();
567
568 /**
569 * List of HistoryRecord objects that have been finished and must
570 * still report back to a pending thumbnail receiver.
571 */
572 final ArrayList mCancelledThumbnails = new ArrayList();
573
574 /**
575 * All of the currently running global content providers. Keys are a
576 * string containing the provider name and values are a
577 * ContentProviderRecord object containing the data about it. Note
578 * that a single provider may be published under multiple names, so
579 * there may be multiple entries here for a single one in mProvidersByClass.
580 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700581 final HashMap<String, ContentProviderRecord> mProvidersByName
582 = new HashMap<String, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800583
584 /**
585 * All of the currently running global content providers. Keys are a
586 * string containing the provider's implementation class and values are a
587 * ContentProviderRecord object containing the data about it.
588 */
Dianne Hackborn1c9b2602011-08-19 14:08:43 -0700589 final HashMap<ComponentName, ContentProviderRecord> mProvidersByClass
590 = new HashMap<ComponentName, ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800591
592 /**
593 * List of content providers who have clients waiting for them. The
594 * application is currently being launched and the provider will be
595 * removed from this list once it is published.
596 */
Dianne Hackborn860755f2010-06-03 18:47:52 -0700597 final ArrayList<ContentProviderRecord> mLaunchingProviders
598 = new ArrayList<ContentProviderRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800599
600 /**
601 * Global set of specific Uri permissions that have been granted.
602 */
603 final private SparseArray<HashMap<Uri, UriPermission>> mGrantedUriPermissions
604 = new SparseArray<HashMap<Uri, UriPermission>>();
605
Svetoslav Ganov54d068e2011-03-02 12:58:40 -0800606 CoreSettingsObserver mCoreSettingsObserver;
607
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800608 /**
609 * Thread-local storage used to carry caller permissions over through
610 * indirect content-provider access.
611 * @see #ActivityManagerService.openContentUri()
612 */
613 private class Identity {
614 public int pid;
615 public int uid;
616
617 Identity(int _pid, int _uid) {
618 pid = _pid;
619 uid = _uid;
620 }
621 }
622 private static ThreadLocal<Identity> sCallerIdentity = new ThreadLocal<Identity>();
623
624 /**
625 * All information we have collected about the runtime performance of
626 * any user id that can impact battery performance.
627 */
628 final BatteryStatsService mBatteryStatsService;
629
630 /**
631 * information about component usage
632 */
633 final UsageStatsService mUsageStatsService;
634
635 /**
636 * Current configuration information. HistoryRecord objects are given
637 * a reference to this object to indicate which configuration they are
638 * currently running in, so this object must be kept immutable.
639 */
640 Configuration mConfiguration = new Configuration();
641
642 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800643 * Current sequencing integer of the configuration, for skipping old
644 * configurations.
645 */
646 int mConfigurationSeq = 0;
647
648 /**
Jack Palevichb90d28c2009-07-22 15:35:24 -0700649 * Hardware-reported OpenGLES version.
650 */
651 final int GL_ES_VERSION;
652
653 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800654 * List of initialization arguments to pass to all processes when binding applications to them.
655 * For example, references to the commonly used services.
656 */
657 HashMap<String, IBinder> mAppBindArgs;
658
659 /**
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700660 * Temporary to avoid allocations. Protected by main lock.
661 */
662 final StringBuilder mStringBuilder = new StringBuilder(256);
663
664 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800665 * Used to control how we initialize the service.
666 */
667 boolean mStartRunning = false;
668 ComponentName mTopComponent;
669 String mTopAction;
670 String mTopData;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700671 boolean mProcessesReady = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800672 boolean mSystemReady = false;
673 boolean mBooting = false;
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700674 boolean mWaitingUpdate = false;
675 boolean mDidUpdate = false;
Dianne Hackborn0d903a82010-09-07 23:51:03 -0700676 boolean mOnBattery = false;
Dianne Hackborn0dad3642010-09-09 21:25:35 -0700677 boolean mLaunchWarningShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800678
679 Context mContext;
680
681 int mFactoryTest;
682
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -0700683 boolean mCheckedForSetup;
684
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800685 /**
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700686 * The time at which we will allow normal application switches again,
687 * after a call to {@link #stopAppSwitches()}.
688 */
689 long mAppSwitchesAllowedTime;
690
691 /**
692 * This is set to true after the first switch after mAppSwitchesAllowedTime
693 * is set; any switches after that will clear the time.
694 */
695 boolean mDidAppSwitch;
696
697 /**
Dianne Hackborn287952c2010-09-22 22:34:31 -0700698 * Last time (in realtime) at which we checked for power usage.
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700699 */
Dianne Hackborn287952c2010-09-22 22:34:31 -0700700 long mLastPowerCheckRealtime;
701
702 /**
703 * Last time (in uptime) at which we checked for power usage.
704 */
705 long mLastPowerCheckUptime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700706
707 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800708 * Set while we are wanting to sleep, to prevent any
709 * activities from being started/resumed.
710 */
711 boolean mSleeping = false;
712
713 /**
Dianne Hackborn55280a92009-05-07 15:53:46 -0700714 * Set if we are shutting down the system, similar to sleeping.
715 */
716 boolean mShuttingDown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800717
718 /**
719 * Task identifier that activities are currently being started
720 * in. Incremented each time a new task is created.
721 * todo: Replace this with a TokenSpace class that generates non-repeating
722 * integers that won't wrap.
723 */
724 int mCurTask = 1;
725
726 /**
727 * Current sequence id for oom_adj computation traversal.
728 */
729 int mAdjSeq = 0;
730
731 /**
Dianne Hackborn906497c2010-05-10 15:57:38 -0700732 * Current sequence id for process LRU updating.
733 */
734 int mLruSeq = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800735
736 /**
Dianne Hackborne02c88a2011-10-28 13:58:15 -0700737 * Keep track of the number of service processes we last found, to
738 * determine on the next iteration which should be B services.
739 */
740 int mNumServiceProcs = 0;
741 int mNewNumServiceProcs = 0;
742
743 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800744 * System monitoring: number of processes that died since the last
745 * N procs were started.
746 */
747 int[] mProcDeaths = new int[20];
748
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700749 /**
750 * This is set if we had to do a delayed dexopt of an app before launching
751 * it, to increasing the ANR timeouts in that case.
752 */
753 boolean mDidDexOpt;
754
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800755 String mDebugApp = null;
756 boolean mWaitForDebugger = false;
757 boolean mDebugTransient = false;
758 String mOrigDebugApp = null;
759 boolean mOrigWaitForDebugger = false;
760 boolean mAlwaysFinishActivities = false;
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700761 IActivityController mController = null;
Dianne Hackborn62f20ec2011-08-15 17:40:28 -0700762 String mProfileApp = null;
763 ProcessRecord mProfileProc = null;
764 String mProfileFile;
765 ParcelFileDescriptor mProfileFd;
766 int mProfileType = 0;
767 boolean mAutoStopProfiler = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800768
Dianne Hackbornb06ea702009-07-13 13:07:51 -0700769 final RemoteCallbackList<IActivityWatcher> mWatchers
770 = new RemoteCallbackList<IActivityWatcher>();
Jeff Sharkeya4620792011-05-20 15:29:23 -0700771
772 final RemoteCallbackList<IProcessObserver> mProcessObservers
773 = new RemoteCallbackList<IProcessObserver>();
774
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800775 /**
776 * Callback of last caller to {@link #requestPss}.
777 */
778 Runnable mRequestPssCallback;
779
780 /**
781 * Remaining processes for which we are waiting results from the last
782 * call to {@link #requestPss}.
783 */
784 final ArrayList<ProcessRecord> mRequestPssList
785 = new ArrayList<ProcessRecord>();
786
787 /**
788 * Runtime statistics collection thread. This object's lock is used to
789 * protect all related state.
790 */
791 final Thread mProcessStatsThread;
792
793 /**
794 * Used to collect process stats when showing not responding dialog.
795 * Protected by mProcessStatsThread.
796 */
797 final ProcessStats mProcessStats = new ProcessStats(
798 MONITOR_THREAD_CPU_USAGE);
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -0700799 final AtomicLong mLastCpuTime = new AtomicLong(0);
800 final AtomicBoolean mProcessStatsMutexFree = new AtomicBoolean(true);
801
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800802 long mLastWriteTime = 0;
803
804 /**
805 * Set to true after the system has finished booting.
806 */
807 boolean mBooted = false;
808
Dianne Hackborn7d608422011-08-07 16:24:18 -0700809 int mProcessLimit = ProcessList.MAX_HIDDEN_APPS;
Dianne Hackbornce86ba82011-07-13 19:33:41 -0700810 int mProcessLimitOverride = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800811
812 WindowManagerService mWindowManager;
813
814 static ActivityManagerService mSelf;
815 static ActivityThread mSystemThread;
816
817 private final class AppDeathRecipient implements IBinder.DeathRecipient {
818 final ProcessRecord mApp;
819 final int mPid;
820 final IApplicationThread mAppThread;
821
822 AppDeathRecipient(ProcessRecord app, int pid,
823 IApplicationThread thread) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800824 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800825 TAG, "New death recipient " + this
826 + " for thread " + thread.asBinder());
827 mApp = app;
828 mPid = pid;
829 mAppThread = thread;
830 }
831
832 public void binderDied() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800833 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800834 TAG, "Death received in " + this
835 + " for thread " + mAppThread.asBinder());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800836 synchronized(ActivityManagerService.this) {
837 appDiedLocked(mApp, mPid, mAppThread);
838 }
839 }
840 }
841
842 static final int SHOW_ERROR_MSG = 1;
843 static final int SHOW_NOT_RESPONDING_MSG = 2;
844 static final int SHOW_FACTORY_ERROR_MSG = 3;
845 static final int UPDATE_CONFIGURATION_MSG = 4;
846 static final int GC_BACKGROUND_PROCESSES_MSG = 5;
847 static final int WAIT_FOR_DEBUGGER_MSG = 6;
848 static final int BROADCAST_INTENT_MSG = 7;
849 static final int BROADCAST_TIMEOUT_MSG = 8;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800850 static final int SERVICE_TIMEOUT_MSG = 12;
851 static final int UPDATE_TIME_ZONE = 13;
852 static final int SHOW_UID_ERROR_MSG = 14;
853 static final int IM_FEELING_LUCKY_MSG = 15;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800854 static final int PROC_START_TIMEOUT_MSG = 20;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700855 static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -0700856 static final int KILL_APPLICATION_MSG = 22;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -0800857 static final int FINALIZE_PENDING_INTENT_MSG = 23;
Dianne Hackborn860755f2010-06-03 18:47:52 -0700858 static final int POST_HEAVY_NOTIFICATION_MSG = 24;
859 static final int CANCEL_HEAVY_NOTIFICATION_MSG = 25;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700860 static final int SHOW_STRICT_MODE_VIOLATION_MSG = 26;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -0700861 static final int CHECK_EXCESSIVE_WAKE_LOCKS_MSG = 27;
Robert Greenwalt03595d02010-11-02 14:08:23 -0700862 static final int CLEAR_DNS_CACHE = 28;
Robert Greenwalt434203a2010-10-11 16:00:27 -0700863 static final int UPDATE_HTTP_PROXY = 29;
Dianne Hackborn36cd41f2011-05-25 21:00:46 -0700864 static final int SHOW_COMPAT_MODE_DIALOG_MSG = 30;
Dianne Hackborn36f80f32011-05-31 18:26:45 -0700865 static final int DISPATCH_FOREGROUND_ACTIVITIES_CHANGED = 31;
866 static final int DISPATCH_PROCESS_DIED = 32;
Dianne Hackborn04d6db32011-11-04 20:07:24 -0700867 static final int REPORT_MEM_USAGE = 33;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800868
869 AlertDialog mUidAlert;
Dianne Hackborn36cd41f2011-05-25 21:00:46 -0700870 CompatModeDialog mCompatModeDialog;
Dianne Hackborn04d6db32011-11-04 20:07:24 -0700871 long mLastMemUsageReportTime = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800872
873 final Handler mHandler = new Handler() {
874 //public Handler() {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800875 // if (localLOGV) Slog.v(TAG, "Handler started!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800876 //}
877
878 public void handleMessage(Message msg) {
879 switch (msg.what) {
880 case SHOW_ERROR_MSG: {
881 HashMap data = (HashMap) msg.obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800882 synchronized (ActivityManagerService.this) {
883 ProcessRecord proc = (ProcessRecord)data.get("app");
884 if (proc != null && proc.crashDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800885 Slog.e(TAG, "App already has crash dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800886 return;
887 }
888 AppErrorResult res = (AppErrorResult) data.get("result");
Dianne Hackborn55280a92009-05-07 15:53:46 -0700889 if (!mSleeping && !mShuttingDown) {
Dan Egnorb7f03672009-12-09 16:22:32 -0800890 Dialog d = new AppErrorDialog(mContext, res, proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800891 d.show();
892 proc.crashDialog = d;
893 } else {
894 // The device is asleep, so just pretend that the user
895 // saw a crash dialog and hit "force quit".
896 res.set(0);
897 }
898 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700899
900 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800901 } break;
902 case SHOW_NOT_RESPONDING_MSG: {
903 synchronized (ActivityManagerService.this) {
904 HashMap data = (HashMap) msg.obj;
905 ProcessRecord proc = (ProcessRecord)data.get("app");
906 if (proc != null && proc.anrDialog != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800907 Slog.e(TAG, "App already has anr dialog: " + proc);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800908 return;
909 }
The Android Open Source Project4df24232009-03-05 14:34:35 -0800910
Dianne Hackborn8891fdc2010-09-20 20:44:46 -0700911 Intent intent = new Intent("android.intent.action.ANR");
912 if (!mProcessesReady) {
913 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
914 }
915 broadcastIntentLocked(null, null, intent,
The Android Open Source Project4df24232009-03-05 14:34:35 -0800916 null, null, 0, null, null, null,
917 false, false, MY_PID, Process.SYSTEM_UID);
918
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800919 Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700920 mContext, proc, (ActivityRecord)data.get("activity"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800921 d.show();
922 proc.anrDialog = d;
923 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -0700924
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700925 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800926 } break;
Brad Fitzpatrick438d0592010-06-10 12:19:19 -0700927 case SHOW_STRICT_MODE_VIOLATION_MSG: {
928 HashMap<String, Object> data = (HashMap<String, Object>) msg.obj;
929 synchronized (ActivityManagerService.this) {
930 ProcessRecord proc = (ProcessRecord) data.get("app");
931 if (proc == null) {
932 Slog.e(TAG, "App not found when showing strict mode dialog.");
933 break;
934 }
935 if (proc.crashDialog != null) {
936 Slog.e(TAG, "App already has strict mode dialog: " + proc);
937 return;
938 }
939 AppErrorResult res = (AppErrorResult) data.get("result");
940 if (!mSleeping && !mShuttingDown) {
941 Dialog d = new StrictModeViolationDialog(mContext, res, proc);
942 d.show();
943 proc.crashDialog = d;
944 } else {
945 // The device is asleep, so just pretend that the user
946 // saw a crash dialog and hit "force quit".
947 res.set(0);
948 }
949 }
950 ensureBootCompleted();
951 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800952 case SHOW_FACTORY_ERROR_MSG: {
953 Dialog d = new FactoryErrorDialog(
954 mContext, msg.getData().getCharSequence("msg"));
955 d.show();
Dianne Hackborn9acc0302009-08-25 00:27:12 -0700956 ensureBootCompleted();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800957 } break;
958 case UPDATE_CONFIGURATION_MSG: {
959 final ContentResolver resolver = mContext.getContentResolver();
960 Settings.System.putConfiguration(resolver, (Configuration)msg.obj);
961 } break;
962 case GC_BACKGROUND_PROCESSES_MSG: {
963 synchronized (ActivityManagerService.this) {
964 performAppGcsIfAppropriateLocked();
965 }
966 } break;
967 case WAIT_FOR_DEBUGGER_MSG: {
968 synchronized (ActivityManagerService.this) {
969 ProcessRecord app = (ProcessRecord)msg.obj;
970 if (msg.arg1 != 0) {
971 if (!app.waitedForDebugger) {
972 Dialog d = new AppWaitingForDebuggerDialog(
973 ActivityManagerService.this,
974 mContext, app);
975 app.waitDialog = d;
976 app.waitedForDebugger = true;
977 d.show();
978 }
979 } else {
980 if (app.waitDialog != null) {
981 app.waitDialog.dismiss();
982 app.waitDialog = null;
983 }
984 }
985 }
986 } break;
987 case BROADCAST_INTENT_MSG: {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800988 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800989 TAG, "Received BROADCAST_INTENT_MSG");
990 processNextBroadcast(true);
991 } break;
992 case BROADCAST_TIMEOUT_MSG: {
Jeff Brown4d94a762010-09-23 11:33:28 -0700993 synchronized (ActivityManagerService.this) {
994 broadcastTimeoutLocked(true);
Jeff Hamiltonacf84742010-05-25 22:10:18 -0500995 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800996 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800997 case SERVICE_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700998 if (mDidDexOpt) {
999 mDidDexOpt = false;
1000 Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
1001 nmsg.obj = msg.obj;
1002 mHandler.sendMessageDelayed(nmsg, SERVICE_TIMEOUT);
1003 return;
1004 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001005 serviceTimeout((ProcessRecord)msg.obj);
1006 } break;
1007 case UPDATE_TIME_ZONE: {
1008 synchronized (ActivityManagerService.this) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001009 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1010 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001011 if (r.thread != null) {
1012 try {
1013 r.thread.updateTimeZone();
1014 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001015 Slog.w(TAG, "Failed to update time zone for: " + r.info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001016 }
1017 }
1018 }
1019 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001020 } break;
Robert Greenwalt03595d02010-11-02 14:08:23 -07001021 case CLEAR_DNS_CACHE: {
1022 synchronized (ActivityManagerService.this) {
1023 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1024 ProcessRecord r = mLruProcesses.get(i);
1025 if (r.thread != null) {
1026 try {
1027 r.thread.clearDnsCache();
1028 } catch (RemoteException ex) {
1029 Slog.w(TAG, "Failed to clear dns cache for: " + r.info.processName);
1030 }
1031 }
1032 }
1033 }
1034 } break;
Robert Greenwalt434203a2010-10-11 16:00:27 -07001035 case UPDATE_HTTP_PROXY: {
1036 ProxyProperties proxy = (ProxyProperties)msg.obj;
1037 String host = "";
1038 String port = "";
1039 String exclList = "";
1040 if (proxy != null) {
1041 host = proxy.getHost();
1042 port = Integer.toString(proxy.getPort());
1043 exclList = proxy.getExclusionList();
1044 }
1045 synchronized (ActivityManagerService.this) {
1046 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
1047 ProcessRecord r = mLruProcesses.get(i);
1048 if (r.thread != null) {
1049 try {
1050 r.thread.setHttpProxy(host, port, exclList);
1051 } catch (RemoteException ex) {
1052 Slog.w(TAG, "Failed to update http proxy for: " +
1053 r.info.processName);
1054 }
1055 }
1056 }
1057 }
1058 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001059 case SHOW_UID_ERROR_MSG: {
1060 // XXX This is a temporary dialog, no need to localize.
1061 AlertDialog d = new BaseErrorDialog(mContext);
1062 d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
1063 d.setCancelable(false);
1064 d.setTitle("System UIDs Inconsistent");
1065 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 +02001066 d.setButton(DialogInterface.BUTTON_POSITIVE, "I'm Feeling Lucky",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001067 mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
1068 mUidAlert = d;
1069 d.show();
1070 } break;
1071 case IM_FEELING_LUCKY_MSG: {
1072 if (mUidAlert != null) {
1073 mUidAlert.dismiss();
1074 mUidAlert = null;
1075 }
1076 } break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001077 case PROC_START_TIMEOUT_MSG: {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001078 if (mDidDexOpt) {
1079 mDidDexOpt = false;
1080 Message nmsg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
1081 nmsg.obj = msg.obj;
1082 mHandler.sendMessageDelayed(nmsg, PROC_START_TIMEOUT);
1083 return;
1084 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001085 ProcessRecord app = (ProcessRecord)msg.obj;
1086 synchronized (ActivityManagerService.this) {
1087 processStartTimedOutLocked(app);
1088 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001089 } break;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07001090 case DO_PENDING_ACTIVITY_LAUNCHES_MSG: {
1091 synchronized (ActivityManagerService.this) {
1092 doPendingActivityLaunchesLocked(true);
1093 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07001094 } break;
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001095 case KILL_APPLICATION_MSG: {
1096 synchronized (ActivityManagerService.this) {
1097 int uid = msg.arg1;
1098 boolean restart = (msg.arg2 == 1);
1099 String pkg = (String) msg.obj;
Christopher Tate3dacd842011-08-19 14:56:15 -07001100 forceStopPackageLocked(pkg, uid, restart, false, true, false);
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07001101 }
1102 } break;
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08001103 case FINALIZE_PENDING_INTENT_MSG: {
1104 ((PendingIntentRecord)msg.obj).completeFinalize();
1105 } break;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001106 case POST_HEAVY_NOTIFICATION_MSG: {
1107 INotificationManager inm = NotificationManager.getService();
1108 if (inm == null) {
1109 return;
1110 }
1111
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001112 ActivityRecord root = (ActivityRecord)msg.obj;
Dianne Hackborn860755f2010-06-03 18:47:52 -07001113 ProcessRecord process = root.app;
1114 if (process == null) {
1115 return;
1116 }
1117
1118 try {
1119 Context context = mContext.createPackageContext(process.info.packageName, 0);
1120 String text = mContext.getString(R.string.heavy_weight_notification,
1121 context.getApplicationInfo().loadLabel(context.getPackageManager()));
1122 Notification notification = new Notification();
1123 notification.icon = com.android.internal.R.drawable.stat_sys_adb; //context.getApplicationInfo().icon;
1124 notification.when = 0;
1125 notification.flags = Notification.FLAG_ONGOING_EVENT;
1126 notification.tickerText = text;
1127 notification.defaults = 0; // please be quiet
1128 notification.sound = null;
1129 notification.vibrate = null;
1130 notification.setLatestEventInfo(context, text,
1131 mContext.getText(R.string.heavy_weight_notification_detail),
1132 PendingIntent.getActivity(mContext, 0, root.intent,
1133 PendingIntent.FLAG_CANCEL_CURRENT));
1134
1135 try {
1136 int[] outId = new int[1];
1137 inm.enqueueNotification("android", R.string.heavy_weight_notification,
1138 notification, outId);
1139 } catch (RuntimeException e) {
1140 Slog.w(ActivityManagerService.TAG,
1141 "Error showing notification for heavy-weight app", e);
1142 } catch (RemoteException e) {
1143 }
1144 } catch (NameNotFoundException e) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07001145 Slog.w(TAG, "Unable to create context for heavy notification", e);
Dianne Hackborn860755f2010-06-03 18:47:52 -07001146 }
1147 } break;
1148 case CANCEL_HEAVY_NOTIFICATION_MSG: {
1149 INotificationManager inm = NotificationManager.getService();
1150 if (inm == null) {
1151 return;
1152 }
1153 try {
1154 inm.cancelNotification("android",
1155 R.string.heavy_weight_notification);
1156 } catch (RuntimeException e) {
1157 Slog.w(ActivityManagerService.TAG,
1158 "Error canceling notification for service", e);
1159 } catch (RemoteException e) {
1160 }
1161 } break;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001162 case CHECK_EXCESSIVE_WAKE_LOCKS_MSG: {
1163 synchronized (ActivityManagerService.this) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001164 checkExcessivePowerUsageLocked(true);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -07001165 removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001166 Message nmsg = obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
1167 sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07001168 }
1169 } break;
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07001170 case SHOW_COMPAT_MODE_DIALOG_MSG: {
1171 synchronized (ActivityManagerService.this) {
1172 ActivityRecord ar = (ActivityRecord)msg.obj;
1173 if (mCompatModeDialog != null) {
1174 if (mCompatModeDialog.mAppInfo.packageName.equals(
1175 ar.info.applicationInfo.packageName)) {
1176 return;
1177 }
1178 mCompatModeDialog.dismiss();
1179 mCompatModeDialog = null;
1180 }
Dianne Hackborn29478262011-06-07 15:44:22 -07001181 if (ar != null && false) {
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07001182 if (mCompatModePackages.getPackageAskCompatModeLocked(
1183 ar.packageName)) {
1184 int mode = mCompatModePackages.computeCompatModeLocked(
1185 ar.info.applicationInfo);
1186 if (mode == ActivityManager.COMPAT_MODE_DISABLED
1187 || mode == ActivityManager.COMPAT_MODE_ENABLED) {
1188 mCompatModeDialog = new CompatModeDialog(
1189 ActivityManagerService.this, mContext,
1190 ar.info.applicationInfo);
1191 mCompatModeDialog.show();
1192 }
1193 }
1194 }
1195 }
Dianne Hackborn36f80f32011-05-31 18:26:45 -07001196 break;
1197 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07001198 case DISPATCH_FOREGROUND_ACTIVITIES_CHANGED: {
Jeff Sharkey287bd832011-05-28 19:36:26 -07001199 final int pid = msg.arg1;
1200 final int uid = msg.arg2;
1201 final boolean foregroundActivities = (Boolean) msg.obj;
1202 dispatchForegroundActivitiesChanged(pid, uid, foregroundActivities);
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07001203 break;
1204 }
1205 case DISPATCH_PROCESS_DIED: {
Jeff Sharkey287bd832011-05-28 19:36:26 -07001206 final int pid = msg.arg1;
1207 final int uid = msg.arg2;
1208 dispatchProcessDied(pid, uid);
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07001209 break;
1210 }
Dianne Hackborn04d6db32011-11-04 20:07:24 -07001211 case REPORT_MEM_USAGE: {
1212 boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
1213 if (!isDebuggable) {
1214 return;
1215 }
1216 synchronized (ActivityManagerService.this) {
1217 long now = SystemClock.uptimeMillis();
Dianne Hackborn7aa6d312011-11-15 15:01:14 -08001218 if (now < (mLastMemUsageReportTime+5*60*1000)) {
1219 // Don't report more than every 5 minutes to somewhat
Dianne Hackborn04d6db32011-11-04 20:07:24 -07001220 // avoid spamming.
1221 return;
1222 }
1223 mLastMemUsageReportTime = now;
1224 }
1225 Thread thread = new Thread() {
1226 @Override public void run() {
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08001227 StringBuilder dropBuilder = new StringBuilder(1024);
1228 StringBuilder logBuilder = new StringBuilder(1024);
Dianne Hackborn672342c2011-11-29 11:29:02 -08001229 StringWriter oomSw = new StringWriter();
1230 PrintWriter oomPw = new PrintWriter(oomSw);
1231 StringWriter catSw = new StringWriter();
1232 PrintWriter catPw = new PrintWriter(catSw);
1233 String[] emptyArgs = new String[] { };
1234 StringBuilder tag = new StringBuilder(128);
1235 StringBuilder stack = new StringBuilder(128);
1236 tag.append("Low on memory -- ");
1237 dumpApplicationMemoryUsage(null, oomPw, " ", emptyArgs, true, catPw,
1238 tag, stack);
1239 dropBuilder.append(stack);
1240 dropBuilder.append('\n');
1241 dropBuilder.append('\n');
1242 String oomString = oomSw.toString();
1243 dropBuilder.append(oomString);
1244 dropBuilder.append('\n');
1245 logBuilder.append(oomString);
Dianne Hackborn04d6db32011-11-04 20:07:24 -07001246 try {
1247 java.lang.Process proc = Runtime.getRuntime().exec(new String[] {
1248 "procrank", });
1249 final InputStreamReader converter = new InputStreamReader(
1250 proc.getInputStream());
1251 BufferedReader in = new BufferedReader(converter);
1252 String line;
1253 while (true) {
1254 line = in.readLine();
1255 if (line == null) {
1256 break;
1257 }
1258 if (line.length() > 0) {
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08001259 logBuilder.append(line);
1260 logBuilder.append('\n');
Dianne Hackborn04d6db32011-11-04 20:07:24 -07001261 }
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08001262 dropBuilder.append(line);
1263 dropBuilder.append('\n');
Dianne Hackborn04d6db32011-11-04 20:07:24 -07001264 }
1265 converter.close();
1266 } catch (IOException e) {
1267 }
Dianne Hackborn7aa6d312011-11-15 15:01:14 -08001268 synchronized (ActivityManagerService.this) {
Dianne Hackborn672342c2011-11-29 11:29:02 -08001269 catPw.println();
Dianne Hackbornee9aef02011-11-16 13:21:46 -08001270 dumpProcessesLocked(null, catPw, emptyArgs, 0, false, null);
Dianne Hackborn7aa6d312011-11-15 15:01:14 -08001271 catPw.println();
Dianne Hackbornee9aef02011-11-16 13:21:46 -08001272 dumpServicesLocked(null, catPw, emptyArgs, 0, false, false, null);
Dianne Hackborn7aa6d312011-11-15 15:01:14 -08001273 catPw.println();
Dianne Hackbornee9aef02011-11-16 13:21:46 -08001274 dumpActivitiesLocked(null, catPw, emptyArgs, 0, false, false, null);
Dianne Hackborn7aa6d312011-11-15 15:01:14 -08001275 }
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08001276 dropBuilder.append(catSw.toString());
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -08001277 addErrorToDropBox("lowmem", null, "system_server", null,
1278 null, tag.toString(), dropBuilder.toString(), null, null);
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08001279 Slog.i(TAG, logBuilder.toString());
Dianne Hackborn04d6db32011-11-04 20:07:24 -07001280 synchronized (ActivityManagerService.this) {
1281 long now = SystemClock.uptimeMillis();
1282 if (mLastMemUsageReportTime < now) {
1283 mLastMemUsageReportTime = now;
1284 }
1285 }
1286 }
1287 };
1288 thread.start();
1289 break;
1290 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001291 }
1292 }
1293 };
1294
1295 public static void setSystemProcess() {
1296 try {
1297 ActivityManagerService m = mSelf;
1298
1299 ServiceManager.addService("activity", m);
1300 ServiceManager.addService("meminfo", new MemBinder(m));
Chet Haase9c1e23b2011-03-24 10:51:31 -07001301 ServiceManager.addService("gfxinfo", new GraphicsBinder(m));
Jeff Brown6754ba22011-12-14 20:20:01 -08001302 ServiceManager.addService("dbinfo", new DbBinder(m));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001303 if (MONITOR_CPU_USAGE) {
1304 ServiceManager.addService("cpuinfo", new CpuBinder(m));
1305 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001306 ServiceManager.addService("permission", new PermissionController(m));
1307
1308 ApplicationInfo info =
1309 mSelf.mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -07001310 "android", STOCK_PM_FLAGS);
Mike Cleron432b7132009-09-24 15:28:29 -07001311 mSystemThread.installSystemApplicationInfo(info);
1312
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001313 synchronized (mSelf) {
1314 ProcessRecord app = mSelf.newProcessRecordLocked(
1315 mSystemThread.getApplicationThread(), info,
1316 info.processName);
1317 app.persistent = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08001318 app.pid = MY_PID;
Dianne Hackborn7d608422011-08-07 16:24:18 -07001319 app.maxAdj = ProcessList.SYSTEM_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001320 mSelf.mProcessNames.put(app.processName, app.info.uid, app);
1321 synchronized (mSelf.mPidsSelfLocked) {
1322 mSelf.mPidsSelfLocked.put(app.pid, app);
1323 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001324 mSelf.updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001325 }
1326 } catch (PackageManager.NameNotFoundException e) {
1327 throw new RuntimeException(
1328 "Unable to find android system package", e);
1329 }
1330 }
1331
1332 public void setWindowManager(WindowManagerService wm) {
1333 mWindowManager = wm;
1334 }
1335
1336 public static final Context main(int factoryTest) {
1337 AThread thr = new AThread();
1338 thr.start();
1339
1340 synchronized (thr) {
1341 while (thr.mService == null) {
1342 try {
1343 thr.wait();
1344 } catch (InterruptedException e) {
1345 }
1346 }
1347 }
1348
1349 ActivityManagerService m = thr.mService;
1350 mSelf = m;
1351 ActivityThread at = ActivityThread.systemMain();
1352 mSystemThread = at;
1353 Context context = at.getSystemContext();
Dianne Hackborn247fe742011-01-08 17:25:57 -08001354 context.setTheme(android.R.style.Theme_Holo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001355 m.mContext = context;
1356 m.mFactoryTest = factoryTest;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001357 m.mMainStack = new ActivityStack(m, context, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001358
1359 m.mBatteryStatsService.publish(context);
1360 m.mUsageStatsService.publish(context);
1361
1362 synchronized (thr) {
1363 thr.mReady = true;
1364 thr.notifyAll();
1365 }
1366
1367 m.startRunning(null, null, null, null);
1368
1369 return context;
1370 }
1371
1372 public static ActivityManagerService self() {
1373 return mSelf;
1374 }
1375
1376 static class AThread extends Thread {
1377 ActivityManagerService mService;
1378 boolean mReady = false;
1379
1380 public AThread() {
1381 super("ActivityManager");
1382 }
1383
1384 public void run() {
1385 Looper.prepare();
1386
1387 android.os.Process.setThreadPriority(
1388 android.os.Process.THREAD_PRIORITY_FOREGROUND);
Christopher Tate160edb32010-06-30 17:46:30 -07001389 android.os.Process.setCanSelfBackground(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001390
1391 ActivityManagerService m = new ActivityManagerService();
1392
1393 synchronized (this) {
1394 mService = m;
1395 notifyAll();
1396 }
1397
1398 synchronized (this) {
1399 while (!mReady) {
1400 try {
1401 wait();
1402 } catch (InterruptedException e) {
1403 }
1404 }
1405 }
1406
Brad Fitzpatrickec062f62010-11-03 09:56:54 -07001407 // For debug builds, log event loop stalls to dropbox for analysis.
1408 if (StrictMode.conditionallyEnableDebugLogging()) {
1409 Slog.i(TAG, "Enabled StrictMode logging for AThread's Looper");
1410 }
1411
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001412 Looper.loop();
1413 }
1414 }
1415
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001416 static class MemBinder extends Binder {
1417 ActivityManagerService mActivityManagerService;
1418 MemBinder(ActivityManagerService activityManagerService) {
1419 mActivityManagerService = activityManagerService;
1420 }
1421
1422 @Override
1423 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Kenny Root3abd75b2011-09-29 11:00:41 -07001424 if (mActivityManagerService.checkCallingPermission(android.Manifest.permission.DUMP)
1425 != PackageManager.PERMISSION_GRANTED) {
1426 pw.println("Permission Denial: can't dump meminfo from from pid="
1427 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
1428 + " without permission " + android.Manifest.permission.DUMP);
1429 return;
1430 }
1431
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -08001432 mActivityManagerService.dumpApplicationMemoryUsage(fd, pw, " ", args,
Dianne Hackborn672342c2011-11-29 11:29:02 -08001433 false, null, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001434 }
1435 }
1436
Chet Haase9c1e23b2011-03-24 10:51:31 -07001437 static class GraphicsBinder extends Binder {
1438 ActivityManagerService mActivityManagerService;
1439 GraphicsBinder(ActivityManagerService activityManagerService) {
1440 mActivityManagerService = activityManagerService;
1441 }
1442
1443 @Override
1444 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Kenny Root3abd75b2011-09-29 11:00:41 -07001445 if (mActivityManagerService.checkCallingPermission(android.Manifest.permission.DUMP)
1446 != PackageManager.PERMISSION_GRANTED) {
1447 pw.println("Permission Denial: can't dump gfxinfo from from pid="
1448 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
1449 + " without permission " + android.Manifest.permission.DUMP);
1450 return;
1451 }
1452
Dianne Hackborne17aeb32011-04-07 15:11:57 -07001453 mActivityManagerService.dumpGraphicsHardwareUsage(fd, pw, args);
Chet Haase9c1e23b2011-03-24 10:51:31 -07001454 }
1455 }
1456
Jeff Brown6754ba22011-12-14 20:20:01 -08001457 static class DbBinder extends Binder {
1458 ActivityManagerService mActivityManagerService;
1459 DbBinder(ActivityManagerService activityManagerService) {
1460 mActivityManagerService = activityManagerService;
1461 }
1462
1463 @Override
1464 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1465 if (mActivityManagerService.checkCallingPermission(android.Manifest.permission.DUMP)
1466 != PackageManager.PERMISSION_GRANTED) {
1467 pw.println("Permission Denial: can't dump dbinfo from from pid="
1468 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
1469 + " without permission " + android.Manifest.permission.DUMP);
1470 return;
1471 }
1472
1473 mActivityManagerService.dumpDbInfo(fd, pw, args);
1474 }
1475 }
1476
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001477 static class CpuBinder extends Binder {
1478 ActivityManagerService mActivityManagerService;
1479 CpuBinder(ActivityManagerService activityManagerService) {
1480 mActivityManagerService = activityManagerService;
1481 }
1482
1483 @Override
1484 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Kenny Root3abd75b2011-09-29 11:00:41 -07001485 if (mActivityManagerService.checkCallingPermission(android.Manifest.permission.DUMP)
1486 != PackageManager.PERMISSION_GRANTED) {
1487 pw.println("Permission Denial: can't dump cpuinfo from from pid="
1488 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
1489 + " without permission " + android.Manifest.permission.DUMP);
1490 return;
1491 }
1492
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001493 synchronized (mActivityManagerService.mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07001494 pw.print(mActivityManagerService.mProcessStats.printCurrentLoad());
1495 pw.print(mActivityManagerService.mProcessStats.printCurrentState(
1496 SystemClock.uptimeMillis()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001497 }
1498 }
1499 }
1500
1501 private ActivityManagerService() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001502 Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
Dianne Hackborn2c6c5e62009-10-08 17:55:49 -07001503
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001504 File dataDir = Environment.getDataDirectory();
1505 File systemDir = new File(dataDir, "system");
1506 systemDir.mkdirs();
1507 mBatteryStatsService = new BatteryStatsService(new File(
1508 systemDir, "batterystats.bin").toString());
1509 mBatteryStatsService.getActiveStatistics().readLocked();
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001510 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
Dianne Hackborn287952c2010-09-22 22:34:31 -07001511 mOnBattery = DEBUG_POWER ? true
1512 : mBatteryStatsService.getActiveStatistics().getIsOnBattery();
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001513 mBatteryStatsService.getActiveStatistics().setCallback(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001514
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001515 mUsageStatsService = new UsageStatsService(new File(
Dianne Hackborn6447ca32009-04-07 19:50:08 -07001516 systemDir, "usagestats").toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001517
Jack Palevichb90d28c2009-07-22 15:35:24 -07001518 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
1519 ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
1520
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001521 mConfiguration.setToDefaults();
1522 mConfiguration.locale = Locale.getDefault();
Dianne Hackborn813075a62011-11-14 17:45:19 -08001523 mConfigurationSeq = mConfiguration.seq = 1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001524 mProcessStats.init();
1525
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07001526 mCompatModePackages = new CompatModePackages(this, systemDir);
1527
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001528 // Add ourself to the Watchdog monitors.
1529 Watchdog.getInstance().addMonitor(this);
1530
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001531 mProcessStatsThread = new Thread("ProcessStats") {
1532 public void run() {
1533 while (true) {
1534 try {
1535 try {
1536 synchronized(this) {
1537 final long now = SystemClock.uptimeMillis();
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001538 long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001539 long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001540 //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001541 // + ", write delay=" + nextWriteDelay);
1542 if (nextWriteDelay < nextCpuDelay) {
1543 nextCpuDelay = nextWriteDelay;
1544 }
1545 if (nextCpuDelay > 0) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001546 mProcessStatsMutexFree.set(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001547 this.wait(nextCpuDelay);
1548 }
1549 }
1550 } catch (InterruptedException e) {
1551 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001552 updateCpuStatsNow();
1553 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001554 Slog.e(TAG, "Unexpected exception collecting process stats", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001555 }
1556 }
1557 }
1558 };
1559 mProcessStatsThread.start();
1560 }
1561
1562 @Override
1563 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1564 throws RemoteException {
1565 try {
1566 return super.onTransact(code, data, reply, flags);
1567 } catch (RuntimeException e) {
1568 // The activity manager only throws security exceptions, so let's
1569 // log all others.
1570 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001571 Slog.e(TAG, "Activity Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001572 }
1573 throw e;
1574 }
1575 }
1576
1577 void updateCpuStats() {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001578 final long now = SystemClock.uptimeMillis();
1579 if (mLastCpuTime.get() >= now - MONITOR_CPU_MIN_TIME) {
1580 return;
1581 }
1582 if (mProcessStatsMutexFree.compareAndSet(true, false)) {
1583 synchronized (mProcessStatsThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001584 mProcessStatsThread.notify();
1585 }
1586 }
1587 }
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001588
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001589 void updateCpuStatsNow() {
1590 synchronized (mProcessStatsThread) {
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001591 mProcessStatsMutexFree.set(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001592 final long now = SystemClock.uptimeMillis();
1593 boolean haveNewCpuStats = false;
Amith Yamasanieaeb6632009-06-03 15:16:10 -07001594
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001595 if (MONITOR_CPU_USAGE &&
Brad Fitzpatrick01fad4a2010-04-19 10:47:40 -07001596 mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
1597 mLastCpuTime.set(now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001598 haveNewCpuStats = true;
1599 mProcessStats.update();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001600 //Slog.i(TAG, mProcessStats.printCurrentState());
1601 //Slog.i(TAG, "Total CPU usage: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001602 // + mProcessStats.getTotalCpuPercent() + "%");
1603
Joe Onorato8a9b2202010-02-26 18:56:32 -08001604 // Slog the cpu usage if the property is set.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001605 if ("true".equals(SystemProperties.get("events.cpu"))) {
1606 int user = mProcessStats.getLastUserTime();
1607 int system = mProcessStats.getLastSystemTime();
1608 int iowait = mProcessStats.getLastIoWaitTime();
1609 int irq = mProcessStats.getLastIrqTime();
1610 int softIrq = mProcessStats.getLastSoftIrqTime();
1611 int idle = mProcessStats.getLastIdleTime();
1612
1613 int total = user + system + iowait + irq + softIrq + idle;
1614 if (total == 0) total = 1;
1615
Doug Zongker2bec3d42009-12-04 12:52:44 -08001616 EventLog.writeEvent(EventLogTags.CPU,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001617 ((user+system+iowait+irq+softIrq) * 100) / total,
1618 (user * 100) / total,
1619 (system * 100) / total,
1620 (iowait * 100) / total,
1621 (irq * 100) / total,
1622 (softIrq * 100) / total);
1623 }
1624 }
1625
Amith Yamasanie43530a2009-08-21 13:11:37 -07001626 long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
Amith Yamasani819f9282009-06-24 23:18:15 -07001627 final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001628 synchronized(bstats) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001629 synchronized(mPidsSelfLocked) {
1630 if (haveNewCpuStats) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001631 if (mOnBattery) {
1632 int perc = bstats.startAddingCpuLocked();
1633 int totalUTime = 0;
1634 int totalSTime = 0;
Dianne Hackborn287952c2010-09-22 22:34:31 -07001635 final int N = mProcessStats.countStats();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001636 for (int i=0; i<N; i++) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001637 ProcessStats.Stats st = mProcessStats.getStats(i);
1638 if (!st.working) {
1639 continue;
1640 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001641 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001642 int otherUTime = (st.rel_utime*perc)/100;
1643 int otherSTime = (st.rel_stime*perc)/100;
1644 totalUTime += otherUTime;
1645 totalSTime += otherSTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001646 if (pr != null) {
1647 BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001648 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1649 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001650 ps.addSpeedStepTimes(cpuSpeedTimes);
Dianne Hackborn287952c2010-09-22 22:34:31 -07001651 pr.curCpuTime += (st.rel_utime+st.rel_stime) * 10;
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001652 } else {
1653 BatteryStatsImpl.Uid.Proc ps =
Amith Yamasani819f9282009-06-24 23:18:15 -07001654 bstats.getProcessStatsLocked(st.name, st.pid);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001655 if (ps != null) {
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001656 ps.addCpuTimeLocked(st.rel_utime-otherUTime,
1657 st.rel_stime-otherSTime);
Amith Yamasanie43530a2009-08-21 13:11:37 -07001658 ps.addSpeedStepTimes(cpuSpeedTimes);
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001659 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001660 }
1661 }
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001662 bstats.finishAddingCpuLocked(perc, totalUTime,
1663 totalSTime, cpuSpeedTimes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001664 }
1665 }
1666 }
Amith Yamasani32dbefd2009-06-19 09:21:17 -07001667
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001668 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
1669 mLastWriteTime = now;
Dianne Hackbornce2ef762010-09-20 11:39:14 -07001670 mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001671 }
1672 }
1673 }
1674 }
1675
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001676 @Override
1677 public void batteryNeedsCpuUpdate() {
1678 updateCpuStatsNow();
1679 }
1680
1681 @Override
1682 public void batteryPowerChanged(boolean onBattery) {
1683 // When plugging in, update the CPU stats first before changing
1684 // the plug state.
1685 updateCpuStatsNow();
1686 synchronized (this) {
1687 synchronized(mPidsSelfLocked) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07001688 mOnBattery = DEBUG_POWER ? true : onBattery;
Dianne Hackborn0d903a82010-09-07 23:51:03 -07001689 }
1690 }
1691 }
1692
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001693 /**
1694 * Initialize the application bind args. These are passed to each
1695 * process when the bindApplication() IPC is sent to the process. They're
1696 * lazily setup to make sure the services are running when they're asked for.
1697 */
1698 private HashMap<String, IBinder> getCommonServicesLocked() {
1699 if (mAppBindArgs == null) {
1700 mAppBindArgs = new HashMap<String, IBinder>();
1701
1702 // Setup the application init args
1703 mAppBindArgs.put("package", ServiceManager.getService("package"));
1704 mAppBindArgs.put("window", ServiceManager.getService("window"));
1705 mAppBindArgs.put(Context.ALARM_SERVICE,
1706 ServiceManager.getService(Context.ALARM_SERVICE));
1707 }
1708 return mAppBindArgs;
1709 }
1710
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001711 final void setFocusedActivityLocked(ActivityRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001712 if (mFocusedActivity != r) {
1713 mFocusedActivity = r;
Dianne Hackbornee9aef02011-11-16 13:21:46 -08001714 if (r != null) {
1715 mWindowManager.setFocusedApp(r.appToken, true);
1716 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001717 }
1718 }
1719
Dianne Hackborn906497c2010-05-10 15:57:38 -07001720 private final void updateLruProcessInternalLocked(ProcessRecord app,
1721 boolean oomAdj, boolean updateActivityTime, int bestPos) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001722 // put it on the LRU to keep track of when it should be exited.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001723 int lrui = mLruProcesses.indexOf(app);
1724 if (lrui >= 0) mLruProcesses.remove(lrui);
1725
1726 int i = mLruProcesses.size()-1;
1727 int skipTop = 0;
1728
Dianne Hackborn906497c2010-05-10 15:57:38 -07001729 app.lruSeq = mLruSeq;
1730
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001731 // compute the new weight for this process.
1732 if (updateActivityTime) {
1733 app.lastActivityTime = SystemClock.uptimeMillis();
1734 }
1735 if (app.activities.size() > 0) {
1736 // If this process has activities, we more strongly want to keep
1737 // it around.
1738 app.lruWeight = app.lastActivityTime;
1739 } else if (app.pubProviders.size() > 0) {
1740 // If this process contains content providers, we want to keep
1741 // it a little more strongly.
Dianne Hackborn7d608422011-08-07 16:24:18 -07001742 app.lruWeight = app.lastActivityTime - ProcessList.CONTENT_APP_IDLE_OFFSET;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001743 // Also don't let it kick out the first few "real" hidden processes.
Dianne Hackborn7d608422011-08-07 16:24:18 -07001744 skipTop = ProcessList.MIN_HIDDEN_APPS;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001745 } else {
1746 // If this process doesn't have activities, we less strongly
1747 // want to keep it around, and generally want to avoid getting
1748 // in front of any very recently used activities.
Dianne Hackborn7d608422011-08-07 16:24:18 -07001749 app.lruWeight = app.lastActivityTime - ProcessList.EMPTY_APP_IDLE_OFFSET;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001750 // Also don't let it kick out the first few "real" hidden processes.
Dianne Hackborn7d608422011-08-07 16:24:18 -07001751 skipTop = ProcessList.MIN_HIDDEN_APPS;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001752 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001753
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001754 while (i >= 0) {
1755 ProcessRecord p = mLruProcesses.get(i);
1756 // If this app shouldn't be in front of the first N background
1757 // apps, then skip over that many that are currently hidden.
Dianne Hackborn7d608422011-08-07 16:24:18 -07001758 if (skipTop > 0 && p.setAdj >= ProcessList.HIDDEN_APP_MIN_ADJ) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001759 skipTop--;
1760 }
Dianne Hackborn906497c2010-05-10 15:57:38 -07001761 if (p.lruWeight <= app.lruWeight || i < bestPos) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08001762 mLruProcesses.add(i+1, app);
1763 break;
1764 }
1765 i--;
1766 }
1767 if (i < 0) {
1768 mLruProcesses.add(0, app);
1769 }
1770
Dianne Hackborn906497c2010-05-10 15:57:38 -07001771 // If the app is currently using a content provider or service,
1772 // bump those processes as well.
1773 if (app.connections.size() > 0) {
1774 for (ConnectionRecord cr : app.connections) {
1775 if (cr.binding != null && cr.binding.service != null
1776 && cr.binding.service.app != null
1777 && cr.binding.service.app.lruSeq != mLruSeq) {
1778 updateLruProcessInternalLocked(cr.binding.service.app, oomAdj,
1779 updateActivityTime, i+1);
1780 }
1781 }
1782 }
1783 if (app.conProviders.size() > 0) {
1784 for (ContentProviderRecord cpr : app.conProviders.keySet()) {
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07001785 if (cpr.proc != null && cpr.proc.lruSeq != mLruSeq) {
1786 updateLruProcessInternalLocked(cpr.proc, oomAdj,
Dianne Hackborn906497c2010-05-10 15:57:38 -07001787 updateActivityTime, i+1);
1788 }
1789 }
1790 }
1791
Joe Onorato8a9b2202010-02-26 18:56:32 -08001792 //Slog.i(TAG, "Putting proc to front: " + app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001793 if (oomAdj) {
1794 updateOomAdjLocked();
1795 }
1796 }
1797
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001798 final void updateLruProcessLocked(ProcessRecord app,
Dianne Hackborn906497c2010-05-10 15:57:38 -07001799 boolean oomAdj, boolean updateActivityTime) {
1800 mLruSeq++;
1801 updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
1802 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07001803
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001804 final ProcessRecord getProcessRecordLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001805 String processName, int uid) {
1806 if (uid == Process.SYSTEM_UID) {
1807 // The system gets to run in any process. If there are multiple
1808 // processes with the same uid, just pick the first (this
1809 // should never happen).
1810 SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(
1811 processName);
1812 return procs != null ? procs.valueAt(0) : null;
1813 }
1814 ProcessRecord proc = mProcessNames.get(processName, uid);
1815 return proc;
1816 }
1817
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001818 void ensurePackageDexOpt(String packageName) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001819 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07001820 try {
1821 if (pm.performDexOpt(packageName)) {
1822 mDidDexOpt = true;
1823 }
1824 } catch (RemoteException e) {
1825 }
1826 }
1827
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001828 boolean isNextTransitionForward() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001829 int transit = mWindowManager.getPendingAppTransition();
1830 return transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
1831 || transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
1832 || transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
1833 }
1834
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07001835 final ProcessRecord startProcessLocked(String processName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001836 ApplicationInfo info, boolean knownToBeDead, int intentFlags,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001837 String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001838 ProcessRecord app = getProcessRecordLocked(processName, info.uid);
1839 // We don't have to do anything more if:
1840 // (1) There is an existing application record; and
1841 // (2) The caller doesn't think it is dead, OR there is no thread
1842 // object attached to it so we know it couldn't have crashed; and
1843 // (3) There is a pid assigned to it, so it is either starting or
1844 // already running.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001845 if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001846 + " app=" + app + " knownToBeDead=" + knownToBeDead
1847 + " thread=" + (app != null ? app.thread : null)
1848 + " pid=" + (app != null ? app.pid : -1));
Magnus Edlund7bb25812010-02-24 15:45:06 +01001849 if (app != null && app.pid > 0) {
1850 if (!knownToBeDead || app.thread == null) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001851 // We already have the app running, or are waiting for it to
1852 // come up (we have a pid but not yet its thread), so keep it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001853 if (DEBUG_PROCESSES) Slog.v(TAG, "App already running: " + app);
Dianne Hackborn6c418d52011-06-29 14:05:33 -07001854 // If this is a new package in the process, add the package to the list
1855 app.addPackage(info.packageName);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001856 return app;
1857 } else {
1858 // An application record is attached to a previous process,
1859 // clean it up now.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001860 if (DEBUG_PROCESSES) Slog.v(TAG, "App died: " + app);
Dianne Hackborn130b0d22011-07-26 22:07:48 -07001861 handleAppDiedLocked(app, true, true);
Magnus Edlund7bb25812010-02-24 15:45:06 +01001862 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001863 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01001864
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001865 String hostingNameStr = hostingName != null
1866 ? hostingName.flattenToShortString() : null;
1867
1868 if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
1869 // If we are in the background, then check to see if this process
1870 // is bad. If so, we will just silently fail.
1871 if (mBadProcesses.get(info.processName, info.uid) != null) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001872 if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid
1873 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001874 return null;
1875 }
1876 } else {
1877 // When the user is explicitly starting a process, then clear its
1878 // crash count so that we won't make it bad until they see at
1879 // least one crash dialog again, and make the process good again
1880 // if it had been bad.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001881 if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
1882 + "/" + info.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001883 mProcessCrashTimes.remove(info.processName, info.uid);
1884 if (mBadProcesses.get(info.processName, info.uid) != null) {
Doug Zongker2bec3d42009-12-04 12:52:44 -08001885 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001886 info.processName);
1887 mBadProcesses.remove(info.processName, info.uid);
1888 if (app != null) {
1889 app.bad = false;
1890 }
1891 }
1892 }
1893
1894 if (app == null) {
1895 app = newProcessRecordLocked(null, info, processName);
1896 mProcessNames.put(processName, info.uid, app);
1897 } else {
1898 // If this is a new package in the process, add the package to the list
1899 app.addPackage(info.packageName);
1900 }
1901
1902 // If the system is not ready yet, then hold off on starting this
1903 // process until it is.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001904 if (!mProcessesReady
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001905 && !isAllowedWhileBooting(info)
1906 && !allowWhileBooting) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001907 if (!mProcessesOnHold.contains(app)) {
1908 mProcessesOnHold.add(app);
1909 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001910 if (DEBUG_PROCESSES) Slog.v(TAG, "System not ready, putting on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001911 return app;
1912 }
1913
1914 startProcessLocked(app, hostingType, hostingNameStr);
1915 return (app.pid != 0) ? app : null;
1916 }
1917
Dianne Hackborn9acc0302009-08-25 00:27:12 -07001918 boolean isAllowedWhileBooting(ApplicationInfo ai) {
1919 return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
1920 }
1921
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001922 private final void startProcessLocked(ProcessRecord app,
1923 String hostingType, String hostingNameStr) {
1924 if (app.pid > 0 && app.pid != MY_PID) {
1925 synchronized (mPidsSelfLocked) {
1926 mPidsSelfLocked.remove(app.pid);
1927 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
1928 }
1929 app.pid = 0;
1930 }
1931
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07001932 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
1933 "startProcessLocked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001934 mProcessesOnHold.remove(app);
1935
1936 updateCpuStats();
1937
1938 System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
1939 mProcDeaths[0] = 0;
1940
1941 try {
1942 int uid = app.info.uid;
1943 int[] gids = null;
1944 try {
1945 gids = mContext.getPackageManager().getPackageGids(
1946 app.info.packageName);
1947 } catch (PackageManager.NameNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001948 Slog.w(TAG, "Unable to retrieve gids", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001949 }
1950 if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {
1951 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
1952 && mTopComponent != null
1953 && app.processName.equals(mTopComponent.getPackageName())) {
1954 uid = 0;
1955 }
1956 if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL
1957 && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
1958 uid = 0;
1959 }
1960 }
1961 int debugFlags = 0;
1962 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
1963 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
Elliott Hughesfa36aee2011-06-17 14:39:41 -07001964 // Also turn on CheckJNI for debuggable apps. It's quite
1965 // awkward to turn on otherwise.
1966 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001967 }
Ben Cheng6c0afff2010-02-14 16:18:56 -08001968 // Run the app in safe mode if its manifest requests so or the
1969 // system is booted in safe mode.
1970 if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
1971 Zygote.systemInSafeMode == true) {
Ben Cheng23085b72010-02-08 16:06:32 -08001972 debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
1973 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001974 if ("1".equals(SystemProperties.get("debug.checkjni"))) {
1975 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
1976 }
Elliott Hughesae07ecf2011-07-06 17:33:27 -07001977 if ("1".equals(SystemProperties.get("debug.jni.logging"))) {
1978 debugFlags |= Zygote.DEBUG_ENABLE_JNI_LOGGING;
1979 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001980 if ("1".equals(SystemProperties.get("debug.assert"))) {
1981 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
1982 }
Jeff Brown3f9dd282011-07-08 20:02:19 -07001983
1984 // Start the process. It will either succeed and return a result containing
1985 // the PID of the new process, or else throw a RuntimeException.
1986 Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
Elliott Hughese1dfcb72011-07-08 11:08:07 -07001987 app.processName, uid, uid, gids, debugFlags,
1988 app.info.targetSdkVersion, null);
Jeff Brown3f9dd282011-07-08 20:02:19 -07001989
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001990 BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
1991 synchronized (bs) {
1992 if (bs.isOnBattery()) {
1993 app.batteryStats.incStartsLocked();
1994 }
1995 }
1996
Jeff Brown3f9dd282011-07-08 20:02:19 -07001997 EventLog.writeEvent(EventLogTags.AM_PROC_START, startResult.pid, uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001998 app.processName, hostingType,
1999 hostingNameStr != null ? hostingNameStr : "");
2000
2001 if (app.persistent) {
Jeff Brown3f9dd282011-07-08 20:02:19 -07002002 Watchdog.getInstance().processStarted(app.processName, startResult.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002003 }
2004
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07002005 StringBuilder buf = mStringBuilder;
2006 buf.setLength(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002007 buf.append("Start proc ");
2008 buf.append(app.processName);
2009 buf.append(" for ");
2010 buf.append(hostingType);
2011 if (hostingNameStr != null) {
2012 buf.append(" ");
2013 buf.append(hostingNameStr);
2014 }
2015 buf.append(": pid=");
Jeff Brown3f9dd282011-07-08 20:02:19 -07002016 buf.append(startResult.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002017 buf.append(" uid=");
2018 buf.append(uid);
2019 buf.append(" gids={");
2020 if (gids != null) {
2021 for (int gi=0; gi<gids.length; gi++) {
2022 if (gi != 0) buf.append(", ");
2023 buf.append(gids[gi]);
2024
2025 }
2026 }
2027 buf.append("}");
Joe Onorato8a9b2202010-02-26 18:56:32 -08002028 Slog.i(TAG, buf.toString());
Jeff Brown3f9dd282011-07-08 20:02:19 -07002029 app.pid = startResult.pid;
2030 app.usingWrapper = startResult.usingWrapper;
2031 app.removed = false;
2032 synchronized (mPidsSelfLocked) {
2033 this.mPidsSelfLocked.put(startResult.pid, app);
2034 Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
2035 msg.obj = app;
2036 mHandler.sendMessageDelayed(msg, startResult.usingWrapper
2037 ? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002038 }
2039 } catch (RuntimeException e) {
2040 // XXX do better error recovery.
2041 app.pid = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002042 Slog.e(TAG, "Failure starting process " + app.processName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002043 }
2044 }
2045
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002046 void updateUsageStats(ActivityRecord resumedComponent, boolean resumed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002047 if (resumed) {
2048 mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
2049 } else {
2050 mUsageStatsService.notePauseComponent(resumedComponent.realActivity);
2051 }
2052 }
2053
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002054 boolean startHomeActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002055 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
2056 && mTopAction == null) {
2057 // We are running in factory test mode, but unable to find
2058 // the factory test app, so just sit around displaying the
2059 // error message and don't try to start anything.
2060 return false;
2061 }
2062 Intent intent = new Intent(
2063 mTopAction,
2064 mTopData != null ? Uri.parse(mTopData) : null);
2065 intent.setComponent(mTopComponent);
2066 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
2067 intent.addCategory(Intent.CATEGORY_HOME);
2068 }
2069 ActivityInfo aInfo =
2070 intent.resolveActivityInfo(mContext.getPackageManager(),
2071 STOCK_PM_FLAGS);
2072 if (aInfo != null) {
2073 intent.setComponent(new ComponentName(
2074 aInfo.applicationInfo.packageName, aInfo.name));
2075 // Don't do this if the home app is currently being
2076 // instrumented.
2077 ProcessRecord app = getProcessRecordLocked(aInfo.processName,
2078 aInfo.applicationInfo.uid);
2079 if (app == null || app.instrumentationClass == null) {
2080 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002081 mMainStack.startActivityLocked(null, intent, null, null, 0, aInfo,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002082 null, null, 0, 0, 0, false, false, null);
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002083 }
2084 }
2085
2086
2087 return true;
2088 }
2089
2090 /**
2091 * Starts the "new version setup screen" if appropriate.
2092 */
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002093 void startSetupActivityLocked() {
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002094 // Only do this once per boot.
2095 if (mCheckedForSetup) {
2096 return;
2097 }
2098
2099 // We will show this screen if the current one is a different
2100 // version than the last one shown, and we are not running in
2101 // low-level factory test mode.
2102 final ContentResolver resolver = mContext.getContentResolver();
2103 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL &&
2104 Settings.Secure.getInt(resolver,
2105 Settings.Secure.DEVICE_PROVISIONED, 0) != 0) {
2106 mCheckedForSetup = true;
2107
2108 // See if we should be showing the platform update setup UI.
2109 Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
2110 List<ResolveInfo> ris = mSelf.mContext.getPackageManager()
2111 .queryIntentActivities(intent, PackageManager.GET_META_DATA);
2112
2113 // We don't allow third party apps to replace this.
2114 ResolveInfo ri = null;
2115 for (int i=0; ris != null && i<ris.size(); i++) {
2116 if ((ris.get(i).activityInfo.applicationInfo.flags
2117 & ApplicationInfo.FLAG_SYSTEM) != 0) {
2118 ri = ris.get(i);
2119 break;
2120 }
2121 }
2122
2123 if (ri != null) {
2124 String vers = ri.activityInfo.metaData != null
2125 ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
2126 : null;
2127 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
2128 vers = ri.activityInfo.applicationInfo.metaData.getString(
2129 Intent.METADATA_SETUP_VERSION);
2130 }
2131 String lastVers = Settings.Secure.getString(
2132 resolver, Settings.Secure.LAST_SETUP_SHOWN);
2133 if (vers != null && !vers.equals(lastVers)) {
2134 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2135 intent.setComponent(new ComponentName(
2136 ri.activityInfo.packageName, ri.activityInfo.name));
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002137 mMainStack.startActivityLocked(null, intent, null, null, 0, ri.activityInfo,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002138 null, null, 0, 0, 0, false, false, null);
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07002139 }
2140 }
2141 }
2142 }
2143
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002144 CompatibilityInfo compatibilityInfoForPackageLocked(ApplicationInfo ai) {
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002145 return mCompatModePackages.compatibilityInfoForPackageLocked(ai);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002146 }
2147
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002148 public int getFrontActivityScreenCompatMode() {
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002149 synchronized (this) {
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002150 return mCompatModePackages.getFrontActivityScreenCompatModeLocked();
2151 }
2152 }
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002153
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002154 public void setFrontActivityScreenCompatMode(int mode) {
2155 synchronized (this) {
2156 mCompatModePackages.setFrontActivityScreenCompatModeLocked(mode);
2157 }
2158 }
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002159
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002160 public int getPackageScreenCompatMode(String packageName) {
2161 synchronized (this) {
2162 return mCompatModePackages.getPackageScreenCompatModeLocked(packageName);
2163 }
2164 }
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002165
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -07002166 public void setPackageScreenCompatMode(String packageName, int mode) {
2167 synchronized (this) {
2168 mCompatModePackages.setPackageScreenCompatModeLocked(packageName, mode);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04002169 }
2170 }
2171
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07002172 public boolean getPackageAskScreenCompat(String packageName) {
2173 synchronized (this) {
2174 return mCompatModePackages.getPackageAskCompatModeLocked(packageName);
2175 }
2176 }
2177
2178 public void setPackageAskScreenCompat(String packageName, boolean ask) {
2179 synchronized (this) {
2180 mCompatModePackages.setPackageAskCompatModeLocked(packageName, ask);
2181 }
2182 }
2183
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002184 void reportResumedActivityLocked(ActivityRecord r) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002185 //Slog.i(TAG, "**** REPORT RESUME: " + r);
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002186
2187 final int identHash = System.identityHashCode(r);
2188 updateUsageStats(r, true);
2189
2190 int i = mWatchers.beginBroadcast();
2191 while (i > 0) {
2192 i--;
2193 IActivityWatcher w = mWatchers.getBroadcastItem(i);
2194 if (w != null) {
2195 try {
2196 w.activityResuming(identHash);
2197 } catch (RemoteException e) {
2198 }
2199 }
2200 }
2201 mWatchers.finishBroadcast();
2202 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002203
Jeff Sharkeya4620792011-05-20 15:29:23 -07002204 private void dispatchForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities) {
2205 int i = mProcessObservers.beginBroadcast();
2206 while (i > 0) {
2207 i--;
2208 final IProcessObserver observer = mProcessObservers.getBroadcastItem(i);
2209 if (observer != null) {
2210 try {
2211 observer.onForegroundActivitiesChanged(pid, uid, foregroundActivities);
2212 } catch (RemoteException e) {
2213 }
2214 }
2215 }
2216 mProcessObservers.finishBroadcast();
2217 }
2218
2219 private void dispatchProcessDied(int pid, int uid) {
2220 int i = mProcessObservers.beginBroadcast();
2221 while (i > 0) {
2222 i--;
2223 final IProcessObserver observer = mProcessObservers.getBroadcastItem(i);
2224 if (observer != null) {
2225 try {
2226 observer.onProcessDied(pid, uid);
2227 } catch (RemoteException e) {
2228 }
2229 }
2230 }
2231 mProcessObservers.finishBroadcast();
2232 }
2233
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002234 final void doPendingActivityLaunchesLocked(boolean doResume) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002235 final int N = mPendingActivityLaunches.size();
2236 if (N <= 0) {
2237 return;
2238 }
2239 for (int i=0; i<N; i++) {
2240 PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002241 mMainStack.startActivityUncheckedLocked(pal.r, pal.sourceRecord,
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07002242 pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
2243 doResume && i == (N-1));
2244 }
2245 mPendingActivityLaunches.clear();
2246 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002247
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002248 public final int startActivity(IApplicationThread caller,
2249 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2250 int grantedMode, IBinder resultTo,
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07002251 String resultWho, int requestCode, boolean onlyIfNeeded, boolean debug,
2252 String profileFile, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002253 return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002254 grantedUriPermissions, grantedMode, resultTo, resultWho,
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07002255 requestCode, onlyIfNeeded, debug, profileFile, profileFd, autoStopProfiler,
2256 null, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002257 }
2258
2259 public final WaitResult startActivityAndWait(IApplicationThread caller,
2260 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2261 int grantedMode, IBinder resultTo,
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07002262 String resultWho, int requestCode, boolean onlyIfNeeded, boolean debug,
2263 String profileFile, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002264 WaitResult res = new WaitResult();
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002265 mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002266 grantedUriPermissions, grantedMode, resultTo, resultWho,
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07002267 requestCode, onlyIfNeeded, debug, profileFile, profileFd, autoStopProfiler,
2268 res, null);
Dianne Hackborn8f7f35e2010-02-25 18:48:12 -08002269 return res;
2270 }
2271
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002272 public final int startActivityWithConfig(IApplicationThread caller,
2273 Intent intent, String resolvedType, Uri[] grantedUriPermissions,
2274 int grantedMode, IBinder resultTo,
2275 String resultWho, int requestCode, boolean onlyIfNeeded,
2276 boolean debug, Configuration config) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002277 return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002278 grantedUriPermissions, grantedMode, resultTo, resultWho,
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07002279 requestCode, onlyIfNeeded, debug, null, null, false, null, config);
Dianne Hackborn2ccda4d2010-03-22 21:49:15 -07002280 }
2281
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002282 public int startActivityIntentSender(IApplicationThread caller,
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002283 IntentSender intent, Intent fillInIntent, String resolvedType,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002284 IBinder resultTo, String resultWho, int requestCode,
2285 int flagsMask, int flagsValues) {
2286 // Refuse possible leaked file descriptors
2287 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
2288 throw new IllegalArgumentException("File descriptors passed in Intent");
2289 }
2290
2291 IIntentSender sender = intent.getTarget();
2292 if (!(sender instanceof PendingIntentRecord)) {
2293 throw new IllegalArgumentException("Bad PendingIntent object");
2294 }
2295
2296 PendingIntentRecord pir = (PendingIntentRecord)sender;
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002297
2298 synchronized (this) {
2299 // If this is coming from the currently resumed activity, it is
2300 // effectively saying that app switches are allowed at this point.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002301 if (mMainStack.mResumedActivity != null
2302 && mMainStack.mResumedActivity.info.applicationInfo.uid ==
Dianne Hackbornfa82f222009-09-17 15:14:12 -07002303 Binder.getCallingUid()) {
2304 mAppSwitchesAllowedTime = 0;
2305 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002306 }
2307
Dianne Hackborn6c418d52011-06-29 14:05:33 -07002308 return pir.sendInner(0, fillInIntent, resolvedType, null,
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002309 null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
2310 }
2311
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002312 public boolean startNextMatchingActivity(IBinder callingActivity,
2313 Intent intent) {
2314 // Refuse possible leaked file descriptors
2315 if (intent != null && intent.hasFileDescriptors() == true) {
2316 throw new IllegalArgumentException("File descriptors passed in Intent");
2317 }
2318
2319 synchronized (this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07002320 ActivityRecord r = mMainStack.isInStackLocked(callingActivity);
2321 if (r == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002322 return false;
2323 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002324 if (r.app == null || r.app.thread == null) {
2325 // The caller is not running... d'oh!
2326 return false;
2327 }
2328 intent = new Intent(intent);
2329 // The caller is not allowed to change the data.
2330 intent.setDataAndType(r.intent.getData(), r.intent.getType());
2331 // And we are resetting to find the next component...
2332 intent.setComponent(null);
2333
2334 ActivityInfo aInfo = null;
2335 try {
2336 List<ResolveInfo> resolves =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002337 AppGlobals.getPackageManager().queryIntentActivities(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002338 intent, r.resolvedType,
Dianne Hackborn1655be42009-05-08 14:29:01 -07002339 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002340
2341 // Look for the original activity in the list...
2342 final int N = resolves != null ? resolves.size() : 0;
2343 for (int i=0; i<N; i++) {
2344 ResolveInfo rInfo = resolves.get(i);
2345 if (rInfo.activityInfo.packageName.equals(r.packageName)
2346 && rInfo.activityInfo.name.equals(r.info.name)) {
2347 // We found the current one... the next matching is
2348 // after it.
2349 i++;
2350 if (i<N) {
2351 aInfo = resolves.get(i).activityInfo;
2352 }
2353 break;
2354 }
2355 }
2356 } catch (RemoteException e) {
2357 }
2358
2359 if (aInfo == null) {
2360 // Nobody who is next!
2361 return false;
2362 }
2363
2364 intent.setComponent(new ComponentName(
2365 aInfo.applicationInfo.packageName, aInfo.name));
2366 intent.setFlags(intent.getFlags()&~(
2367 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
2368 Intent.FLAG_ACTIVITY_CLEAR_TOP|
2369 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
2370 Intent.FLAG_ACTIVITY_NEW_TASK));
2371
2372 // Okay now we need to start the new activity, replacing the
2373 // currently running activity. This is a little tricky because
2374 // we want to start the new one as if the current one is finished,
2375 // but not finish the current one first so that there is no flicker.
2376 // And thus...
2377 final boolean wasFinishing = r.finishing;
2378 r.finishing = true;
2379
2380 // Propagate reply information over to the new activity.
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002381 final ActivityRecord resultTo = r.resultTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002382 final String resultWho = r.resultWho;
2383 final int requestCode = r.requestCode;
2384 r.resultTo = null;
2385 if (resultTo != null) {
2386 resultTo.removeResultsLocked(r, resultWho, requestCode);
2387 }
2388
2389 final long origId = Binder.clearCallingIdentity();
2390 // XXX we are not dealing with propagating grantedUriPermissions...
2391 // those are not yet exposed to user code, so there is no need.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002392 int res = mMainStack.startActivityLocked(r.app.thread, intent,
Dianne Hackbornbe707852011-11-11 14:32:10 -08002393 r.resolvedType, null, 0, aInfo,
2394 resultTo != null ? resultTo.appToken : null, resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002395 requestCode, -1, r.launchedFromUid, false, false, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002396 Binder.restoreCallingIdentity(origId);
2397
2398 r.finishing = wasFinishing;
2399 if (res != START_SUCCESS) {
2400 return false;
2401 }
2402 return true;
2403 }
2404 }
2405
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002406 public final int startActivityInPackage(int uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002407 Intent intent, String resolvedType, IBinder resultTo,
2408 String resultWho, int requestCode, boolean onlyIfNeeded) {
Dianne Hackborn2d91af02009-07-16 13:34:33 -07002409
2410 // This is so super not safe, that only the system (or okay root)
2411 // can do it.
2412 final int callingUid = Binder.getCallingUid();
2413 if (callingUid != 0 && callingUid != Process.myUid()) {
2414 throw new SecurityException(
2415 "startActivityInPackage only available to the system");
2416 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002417
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002418 return mMainStack.startActivityMayWait(null, uid, intent, resolvedType,
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07002419 null, 0, resultTo, resultWho, requestCode, onlyIfNeeded, false,
2420 null, null, false, null, null);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002421 }
2422
2423 public final int startActivities(IApplicationThread caller,
2424 Intent[] intents, String[] resolvedTypes, IBinder resultTo) {
2425 return mMainStack.startActivities(caller, -1, intents, resolvedTypes, resultTo);
2426 }
2427
2428 public final int startActivitiesInPackage(int uid,
2429 Intent[] intents, String[] resolvedTypes, IBinder resultTo) {
2430
2431 // This is so super not safe, that only the system (or okay root)
2432 // can do it.
2433 final int callingUid = Binder.getCallingUid();
2434 if (callingUid != 0 && callingUid != Process.myUid()) {
2435 throw new SecurityException(
2436 "startActivityInPackage only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002437 }
2438
Dianne Hackborn621e17d2010-11-22 15:59:56 -08002439 return mMainStack.startActivities(null, uid, intents, resolvedTypes, resultTo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002440 }
2441
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002442 final void addRecentTaskLocked(TaskRecord task) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002443 int N = mRecentTasks.size();
Dianne Hackborn7c0e75e2010-12-21 19:15:40 -08002444 // Quick case: check if the top-most recent task is the same.
2445 if (N > 0 && mRecentTasks.get(0) == task) {
2446 return;
2447 }
2448 // Remove any existing entries that are the same kind of task.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002449 for (int i=0; i<N; i++) {
2450 TaskRecord tr = mRecentTasks.get(i);
2451 if ((task.affinity != null && task.affinity.equals(tr.affinity))
2452 || (task.intent != null && task.intent.filterEquals(tr.intent))) {
2453 mRecentTasks.remove(i);
2454 i--;
2455 N--;
2456 if (task.intent == null) {
2457 // If the new recent task we are adding is not fully
2458 // specified, then replace it with the existing recent task.
2459 task = tr;
2460 }
2461 }
2462 }
2463 if (N >= MAX_RECENT_TASKS) {
2464 mRecentTasks.remove(N-1);
2465 }
2466 mRecentTasks.add(0, task);
2467 }
2468
2469 public void setRequestedOrientation(IBinder token,
2470 int requestedOrientation) {
2471 synchronized (this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07002472 ActivityRecord r = mMainStack.isInStackLocked(token);
2473 if (r == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002474 return;
2475 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002476 final long origId = Binder.clearCallingIdentity();
Dianne Hackbornbe707852011-11-11 14:32:10 -08002477 mWindowManager.setAppOrientation(r.appToken, requestedOrientation);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002478 Configuration config = mWindowManager.updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07002479 mConfiguration,
Dianne Hackbornbe707852011-11-11 14:32:10 -08002480 r.mayFreezeScreenLocked(r.app) ? r.appToken : null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002481 if (config != null) {
2482 r.frozenBeforeDestroy = true;
Dianne Hackborn813075a62011-11-14 17:45:19 -08002483 if (!updateConfigurationLocked(config, r, false, false)) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002484 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002485 }
2486 }
2487 Binder.restoreCallingIdentity(origId);
2488 }
2489 }
2490
2491 public int getRequestedOrientation(IBinder token) {
2492 synchronized (this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07002493 ActivityRecord r = mMainStack.isInStackLocked(token);
2494 if (r == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002495 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
2496 }
Dianne Hackbornbe707852011-11-11 14:32:10 -08002497 return mWindowManager.getAppOrientation(r.appToken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002498 }
2499 }
2500
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002501 /**
2502 * This is the internal entry point for handling Activity.finish().
2503 *
2504 * @param token The Binder token referencing the Activity we want to finish.
2505 * @param resultCode Result code, if any, from this Activity.
2506 * @param resultData Result data (Intent), if any, from this Activity.
2507 *
Alexey Tarasov83bad3d2009-08-12 15:05:43 +11002508 * @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 -08002509 */
2510 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
2511 // Refuse possible leaked file descriptors
2512 if (resultData != null && resultData.hasFileDescriptors() == true) {
2513 throw new IllegalArgumentException("File descriptors passed in Intent");
2514 }
2515
2516 synchronized(this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002517 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002518 // Find the first activity that is not finishing.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002519 ActivityRecord next = mMainStack.topRunningActivityLocked(token, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002520 if (next != null) {
2521 // ask watcher if this is allowed
2522 boolean resumeOK = true;
2523 try {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002524 resumeOK = mController.activityResuming(next.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002525 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07002526 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002527 }
2528
2529 if (!resumeOK) {
2530 return false;
2531 }
2532 }
2533 }
2534 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002535 boolean res = mMainStack.requestFinishActivityLocked(token, resultCode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002536 resultData, "app-request");
2537 Binder.restoreCallingIdentity(origId);
2538 return res;
2539 }
2540 }
2541
Dianne Hackborn860755f2010-06-03 18:47:52 -07002542 public final void finishHeavyWeightApp() {
2543 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2544 != PackageManager.PERMISSION_GRANTED) {
2545 String msg = "Permission Denial: finishHeavyWeightApp() from pid="
2546 + Binder.getCallingPid()
2547 + ", uid=" + Binder.getCallingUid()
2548 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2549 Slog.w(TAG, msg);
2550 throw new SecurityException(msg);
2551 }
2552
2553 synchronized(this) {
2554 if (mHeavyWeightProcess == null) {
2555 return;
2556 }
2557
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002558 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>(
Dianne Hackborn860755f2010-06-03 18:47:52 -07002559 mHeavyWeightProcess.activities);
2560 for (int i=0; i<activities.size(); i++) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07002561 ActivityRecord r = activities.get(i);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002562 if (!r.finishing) {
Dianne Hackbornbe707852011-11-11 14:32:10 -08002563 int index = mMainStack.indexOfTokenLocked(r.appToken);
Dianne Hackborn860755f2010-06-03 18:47:52 -07002564 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002565 mMainStack.finishActivityLocked(r, index, Activity.RESULT_CANCELED,
Dianne Hackborn860755f2010-06-03 18:47:52 -07002566 null, "finish-heavy");
2567 }
2568 }
2569 }
2570
2571 mHeavyWeightProcess = null;
2572 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
2573 }
2574 }
2575
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002576 public void crashApplication(int uid, int initialPid, String packageName,
2577 String message) {
2578 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
2579 != PackageManager.PERMISSION_GRANTED) {
2580 String msg = "Permission Denial: crashApplication() from pid="
2581 + Binder.getCallingPid()
2582 + ", uid=" + Binder.getCallingUid()
2583 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
2584 Slog.w(TAG, msg);
2585 throw new SecurityException(msg);
2586 }
2587
2588 synchronized(this) {
2589 ProcessRecord proc = null;
2590
2591 // Figure out which process to kill. We don't trust that initialPid
2592 // still has any relation to current pids, so must scan through the
2593 // list.
2594 synchronized (mPidsSelfLocked) {
2595 for (int i=0; i<mPidsSelfLocked.size(); i++) {
2596 ProcessRecord p = mPidsSelfLocked.valueAt(i);
2597 if (p.info.uid != uid) {
2598 continue;
2599 }
2600 if (p.pid == initialPid) {
2601 proc = p;
2602 break;
2603 }
2604 for (String str : p.pkgList) {
2605 if (str.equals(packageName)) {
2606 proc = p;
2607 }
2608 }
2609 }
2610 }
2611
2612 if (proc == null) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07002613 Slog.w(TAG, "crashApplication: nothing for uid=" + uid
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002614 + " initialPid=" + initialPid
2615 + " packageName=" + packageName);
2616 return;
2617 }
2618
2619 if (proc.thread != null) {
Dianne Hackborn9f531192010-08-04 17:48:03 -07002620 if (proc.pid == Process.myPid()) {
2621 Log.w(TAG, "crashApplication: trying to crash self!");
2622 return;
2623 }
Dianne Hackborn9d39d0c2010-06-24 15:57:42 -07002624 long ident = Binder.clearCallingIdentity();
2625 try {
2626 proc.thread.scheduleCrash(message);
2627 } catch (RemoteException e) {
2628 }
2629 Binder.restoreCallingIdentity(ident);
2630 }
2631 }
2632 }
2633
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002634 public final void finishSubActivity(IBinder token, String resultWho,
2635 int requestCode) {
2636 synchronized(this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07002637 ActivityRecord self = mMainStack.isInStackLocked(token);
2638 if (self == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002639 return;
2640 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002641
2642 final long origId = Binder.clearCallingIdentity();
2643
2644 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002645 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2646 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002647 if (r.resultTo == self && r.requestCode == requestCode) {
2648 if ((r.resultWho == null && resultWho == null) ||
2649 (r.resultWho != null && r.resultWho.equals(resultWho))) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002650 mMainStack.finishActivityLocked(r, i,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002651 Activity.RESULT_CANCELED, null, "request-sub");
2652 }
2653 }
2654 }
2655
2656 Binder.restoreCallingIdentity(origId);
2657 }
2658 }
2659
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002660 public boolean willActivityBeVisible(IBinder token) {
2661 synchronized(this) {
2662 int i;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002663 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
2664 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackbornbe707852011-11-11 14:32:10 -08002665 if (r.appToken == token) {
Dianne Hackborn061d58a2010-03-12 15:07:06 -08002666 return true;
2667 }
2668 if (r.fullscreen && !r.finishing) {
2669 return false;
2670 }
2671 }
2672 return true;
2673 }
2674 }
2675
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002676 public void overridePendingTransition(IBinder token, String packageName,
2677 int enterAnim, int exitAnim) {
2678 synchronized(this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07002679 ActivityRecord self = mMainStack.isInStackLocked(token);
2680 if (self == null) {
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002681 return;
2682 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002683
2684 final long origId = Binder.clearCallingIdentity();
2685
2686 if (self.state == ActivityState.RESUMED
2687 || self.state == ActivityState.PAUSING) {
2688 mWindowManager.overridePendingAppTransition(packageName,
2689 enterAnim, exitAnim);
2690 }
2691
2692 Binder.restoreCallingIdentity(origId);
2693 }
2694 }
2695
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002696 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002697 * Main function for removing an existing process from the activity manager
2698 * as a result of that process going away. Clears out all connections
2699 * to the process.
2700 */
2701 private final void handleAppDiedLocked(ProcessRecord app,
Dianne Hackborn130b0d22011-07-26 22:07:48 -07002702 boolean restarting, boolean allowRestart) {
2703 cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002704 if (!restarting) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002705 mLruProcesses.remove(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002706 }
2707
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07002708 if (mProfileProc == app) {
2709 clearProfilerLocked();
2710 }
2711
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002712 // Just in case...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002713 if (mMainStack.mPausingActivity != null && mMainStack.mPausingActivity.app == app) {
2714 if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " +mMainStack.mPausingActivity);
2715 mMainStack.mPausingActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002716 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002717 if (mMainStack.mLastPausedActivity != null && mMainStack.mLastPausedActivity.app == app) {
2718 mMainStack.mLastPausedActivity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002719 }
2720
2721 // Remove this application's activities from active lists.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002722 mMainStack.removeHistoryRecordsForAppLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002723
2724 boolean atTop = true;
2725 boolean hasVisibleActivities = false;
2726
2727 // Clean out the history list.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002728 int i = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002729 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002730 TAG, "Removing app " + app + " from history with " + i + " entries");
2731 while (i > 0) {
2732 i--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002733 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002734 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002735 TAG, "Record #" + i + " " + r + ": app=" + r.app);
2736 if (r.app == app) {
2737 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
Dianne Hackborn98cfebc2011-10-18 13:17:33 -07002738 if (ActivityStack.DEBUG_ADD_REMOVE) {
2739 RuntimeException here = new RuntimeException("here");
2740 here.fillInStackTrace();
2741 Slog.i(TAG, "Removing activity " + r + " from stack at " + i
2742 + ": haveState=" + r.haveState
2743 + " stateNotNeeded=" + r.stateNotNeeded
2744 + " finishing=" + r.finishing
2745 + " state=" + r.state, here);
2746 }
2747 if (!r.finishing) {
2748 Slog.w(TAG, "Force removing " + r + ": app died, no saved state");
Dianne Hackborn8bf0aa92011-11-29 13:54:43 -08002749 EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
2750 System.identityHashCode(r),
2751 r.task.taskId, r.shortComponentName,
2752 "proc died without state saved");
Dianne Hackborn98cfebc2011-10-18 13:17:33 -07002753 }
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -08002754 r.makeFinishing();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002755 mMainStack.mHistory.remove(i);
Dianne Hackbornf26fd992011-04-08 18:14:09 -07002756 r.takeFromHistory();
Dianne Hackbornbe707852011-11-11 14:32:10 -08002757 mWindowManager.removeAppToken(r.appToken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002758 if (VALIDATE_TOKENS) {
Dianne Hackbornbe707852011-11-11 14:32:10 -08002759 mMainStack.validateAppTokensLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002760 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002761 r.removeUriPermissionsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002762
2763 } else {
2764 // We have the current state for this activity, so
2765 // it can be restarted later when needed.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002766 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002767 TAG, "Keeping entry, setting app to null");
2768 if (r.visible) {
2769 hasVisibleActivities = true;
2770 }
2771 r.app = null;
2772 r.nowVisible = false;
2773 if (!r.haveState) {
Dianne Hackborn98cfebc2011-10-18 13:17:33 -07002774 if (ActivityStack.DEBUG_SAVED_STATE) Slog.i(TAG,
2775 "App died, clearing saved state of " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002776 r.icicle = null;
2777 }
2778 }
2779
Dianne Hackbornce86ba82011-07-13 19:33:41 -07002780 r.stack.cleanUpActivityLocked(r, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002781 }
2782 atTop = false;
2783 }
2784
2785 app.activities.clear();
2786
2787 if (app.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002788 Slog.w(TAG, "Crash of app " + app.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002789 + " running instrumentation " + app.instrumentationClass);
2790 Bundle info = new Bundle();
2791 info.putString("shortMsg", "Process crashed.");
2792 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
2793 }
2794
2795 if (!restarting) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002796 if (!mMainStack.resumeTopActivityLocked(null)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002797 // If there was nothing to resume, and we are not already
2798 // restarting this process, but there is a visible activity that
2799 // is hosted by the process... then make sure all visible
2800 // activities are running, taking care of restarting this
2801 // process.
2802 if (hasVisibleActivities) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002803 mMainStack.ensureActivitiesVisibleLocked(null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002804 }
2805 }
2806 }
2807 }
2808
2809 private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
2810 IBinder threadBinder = thread.asBinder();
2811
2812 // Find the application record.
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002813 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2814 ProcessRecord rec = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002815 if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
2816 return i;
2817 }
2818 }
2819 return -1;
2820 }
2821
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002822 final ProcessRecord getRecordForAppLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002823 IApplicationThread thread) {
2824 if (thread == null) {
2825 return null;
2826 }
2827
2828 int appIndex = getLRURecordIndexForAppLocked(thread);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002829 return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002830 }
2831
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07002832 final void appDiedLocked(ProcessRecord app, int pid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002833 IApplicationThread thread) {
2834
2835 mProcDeaths[0]++;
2836
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07002837 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
2838 synchronized (stats) {
2839 stats.noteProcessDiedLocked(app.info.uid, pid);
2840 }
2841
Magnus Edlund7bb25812010-02-24 15:45:06 +01002842 // Clean up already done if the process has been re-started.
2843 if (app.pid == pid && app.thread != null &&
2844 app.thread.asBinder() == thread.asBinder()) {
Dianne Hackborn906497c2010-05-10 15:57:38 -07002845 if (!app.killedBackground) {
2846 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
2847 + ") has died.");
2848 }
Doug Zongker2bec3d42009-12-04 12:52:44 -08002849 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002850 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002851 TAG, "Dying app: " + app + ", pid: " + pid
2852 + ", thread: " + thread.asBinder());
2853 boolean doLowMem = app.instrumentationClass == null;
Dianne Hackborn130b0d22011-07-26 22:07:48 -07002854 handleAppDiedLocked(app, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002855
2856 if (doLowMem) {
2857 // If there are no longer any background processes running,
2858 // and the app that died was not running instrumentation,
2859 // then tell everyone we are now low on memory.
2860 boolean haveBg = false;
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002861 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2862 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn7d608422011-08-07 16:24:18 -07002863 if (rec.thread != null && rec.setAdj >= ProcessList.HIDDEN_APP_MIN_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002864 haveBg = true;
2865 break;
2866 }
2867 }
2868
2869 if (!haveBg) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002870 EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002871 long now = SystemClock.uptimeMillis();
Dianne Hackborndd71fc82009-12-16 19:24:32 -08002872 for (int i=mLruProcesses.size()-1; i>=0; i--) {
2873 ProcessRecord rec = mLruProcesses.get(i);
Dianne Hackborn36124872009-10-08 16:22:03 -07002874 if (rec != app && rec.thread != null &&
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002875 (rec.lastLowMemory+GC_MIN_INTERVAL) <= now) {
2876 // The low memory report is overriding any current
2877 // state for a GC request. Make sure to do
Dianne Hackborn32907cf2010-06-10 17:50:20 -07002878 // heavy/important/visible/foreground processes first.
Dianne Hackborn7d608422011-08-07 16:24:18 -07002879 if (rec.setAdj <= ProcessList.HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002880 rec.lastRequestedGc = 0;
2881 } else {
2882 rec.lastRequestedGc = rec.lastLowMemory;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002883 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002884 rec.reportLowMemory = true;
2885 rec.lastLowMemory = now;
2886 mProcessesToGc.remove(rec);
2887 addProcessToGcListLocked(rec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002888 }
2889 }
Dianne Hackborn04d6db32011-11-04 20:07:24 -07002890 mHandler.sendEmptyMessage(REPORT_MEM_USAGE);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07002891 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002892 }
2893 }
Magnus Edlund7bb25812010-02-24 15:45:06 +01002894 } else if (app.pid != pid) {
2895 // A new process has already been started.
Joe Onorato8a9b2202010-02-26 18:56:32 -08002896 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
Magnus Edlund7bb25812010-02-24 15:45:06 +01002897 + ") has died and restarted (pid " + app.pid + ").");
Dianne Hackborn28a8c2b2010-03-01 11:30:02 -08002898 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.pid, app.processName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08002899 } else if (DEBUG_PROCESSES) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002900 Slog.d(TAG, "Received spurious death notification for thread "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002901 + thread.asBinder());
2902 }
2903 }
2904
Dan Egnor42471dd2010-01-07 17:25:22 -08002905 /**
2906 * If a stack trace dump file is configured, dump process stack traces.
Christopher Tate6ee412d2010-05-28 12:01:56 -07002907 * @param clearTraces causes the dump file to be erased prior to the new
2908 * traces being written, if true; when false, the new traces will be
2909 * appended to any existing file content.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002910 * @param firstPids of dalvik VM processes to dump stack traces for first
2911 * @param lastPids of dalvik VM processes to dump stack traces for last
Dan Egnor42471dd2010-01-07 17:25:22 -08002912 * @return file containing stack traces, or null if no dump file is configured
2913 */
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002914 public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> firstPids,
2915 ProcessStats processStats, SparseArray<Boolean> lastPids) {
Dan Egnor42471dd2010-01-07 17:25:22 -08002916 String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
2917 if (tracesPath == null || tracesPath.length() == 0) {
2918 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002919 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002920
2921 File tracesFile = new File(tracesPath);
2922 try {
2923 File tracesDir = tracesFile.getParentFile();
2924 if (!tracesDir.exists()) tracesFile.mkdirs();
2925 FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
2926
Christopher Tate6ee412d2010-05-28 12:01:56 -07002927 if (clearTraces && tracesFile.exists()) tracesFile.delete();
Dan Egnor42471dd2010-01-07 17:25:22 -08002928 tracesFile.createNewFile();
2929 FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
2930 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002931 Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
Dan Egnor42471dd2010-01-07 17:25:22 -08002932 return null;
2933 }
2934
2935 // Use a FileObserver to detect when traces finish writing.
2936 // The order of traces is considered important to maintain for legibility.
2937 FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
2938 public synchronized void onEvent(int event, String path) { notify(); }
2939 };
2940
2941 try {
2942 observer.startWatching();
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002943
2944 // First collect all of the stacks of the most important pids.
2945 try {
2946 int num = firstPids.size();
2947 for (int i = 0; i < num; i++) {
2948 synchronized (observer) {
2949 Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT);
2950 observer.wait(200); // Wait for write-close, give up after 200msec
2951 }
2952 }
2953 } catch (InterruptedException e) {
2954 Log.wtf(TAG, e);
2955 }
2956
2957 // Next measure CPU usage.
2958 if (processStats != null) {
2959 processStats.init();
2960 System.gc();
2961 processStats.update();
2962 try {
2963 synchronized (processStats) {
2964 processStats.wait(500); // measure over 1/2 second.
2965 }
2966 } catch (InterruptedException e) {
2967 }
2968 processStats.update();
2969
2970 // We'll take the stack crawls of just the top apps using CPU.
2971 final int N = processStats.countWorkingStats();
2972 int numProcs = 0;
2973 for (int i=0; i<N && numProcs<5; i++) {
2974 ProcessStats.Stats stats = processStats.getWorkingStats(i);
2975 if (lastPids.indexOfKey(stats.pid) >= 0) {
2976 numProcs++;
2977 try {
2978 synchronized (observer) {
2979 Process.sendSignal(stats.pid, Process.SIGNAL_QUIT);
2980 observer.wait(200); // Wait for write-close, give up after 200msec
2981 }
2982 } catch (InterruptedException e) {
2983 Log.wtf(TAG, e);
2984 }
2985
2986 }
Dan Egnor42471dd2010-01-07 17:25:22 -08002987 }
2988 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07002989
2990 return tracesFile;
2991
Dan Egnor42471dd2010-01-07 17:25:22 -08002992 } finally {
2993 observer.stopWatching();
2994 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002995 }
2996
Jeff Brown4d94a762010-09-23 11:33:28 -07002997 private final class AppNotResponding implements Runnable {
2998 private final ProcessRecord mApp;
2999 private final String mAnnotation;
3000
3001 public AppNotResponding(ProcessRecord app, String annotation) {
3002 mApp = app;
3003 mAnnotation = annotation;
3004 }
3005
3006 @Override
3007 public void run() {
3008 appNotResponding(mApp, null, null, mAnnotation);
3009 }
3010 }
3011
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003012 final void appNotResponding(ProcessRecord app, ActivityRecord activity,
3013 ActivityRecord parent, final String annotation) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003014 ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
3015 SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20);
3016
Dianne Hackborn287952c2010-09-22 22:34:31 -07003017 if (mController != null) {
3018 try {
3019 // 0 == continue, -1 = kill process immediately
3020 int res = mController.appEarlyNotResponding(app.processName, app.pid, annotation);
3021 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
3022 } catch (RemoteException e) {
3023 mController = null;
3024 }
3025 }
3026
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003027 long anrTime = SystemClock.uptimeMillis();
3028 if (MONITOR_CPU_USAGE) {
3029 updateCpuStatsNow();
3030 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003031
3032 synchronized (this) {
3033 // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
3034 if (mShuttingDown) {
3035 Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
3036 return;
3037 } else if (app.notResponding) {
3038 Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
3039 return;
3040 } else if (app.crashing) {
3041 Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
3042 return;
3043 }
3044
3045 // In case we come through here for the same app before completing
3046 // this one, mark as anring now so we will bail out.
3047 app.notResponding = true;
Dan Egnor42471dd2010-01-07 17:25:22 -08003048
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003049 // Log the ANR to the event log.
3050 EventLog.writeEvent(EventLogTags.AM_ANR, app.pid, app.processName, app.info.flags,
3051 annotation);
Dan Egnor42471dd2010-01-07 17:25:22 -08003052
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003053 // Dump thread traces as quickly as we can, starting with "interesting" processes.
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003054 firstPids.add(app.pid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003055
3056 int parentPid = app.pid;
3057 if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003058 if (parentPid != app.pid) firstPids.add(parentPid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003059
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003060 if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID);
Dan Egnor42471dd2010-01-07 17:25:22 -08003061
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003062 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
3063 ProcessRecord r = mLruProcesses.get(i);
3064 if (r != null && r.thread != null) {
3065 int pid = r.pid;
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003066 if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
3067 if (r.persistent) {
3068 firstPids.add(pid);
3069 } else {
3070 lastPids.put(pid, Boolean.TRUE);
3071 }
3072 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003073 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003074 }
3075 }
3076
Dan Egnor42471dd2010-01-07 17:25:22 -08003077 // Log the ANR to the main log.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07003078 StringBuilder info = mStringBuilder;
3079 info.setLength(0);
Dan Egnor42471dd2010-01-07 17:25:22 -08003080 info.append("ANR in ").append(app.processName);
3081 if (activity != null && activity.shortComponentName != null) {
3082 info.append(" (").append(activity.shortComponentName).append(")");
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07003083 }
Eric Rowe6f4f6192010-02-17 18:29:04 -08003084 info.append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003085 if (annotation != null) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08003086 info.append("Reason: ").append(annotation).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003087 }
Dan Egnor42471dd2010-01-07 17:25:22 -08003088 if (parent != null && parent != activity) {
Eric Rowe6f4f6192010-02-17 18:29:04 -08003089 info.append("Parent: ").append(parent.shortComponentName).append("\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003090 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003091
Dianne Hackborn287952c2010-09-22 22:34:31 -07003092 final ProcessStats processStats = new ProcessStats(true);
3093
3094 File tracesFile = dumpStackTraces(true, firstPids, processStats, lastPids);
3095
Dan Egnor42471dd2010-01-07 17:25:22 -08003096 String cpuInfo = null;
3097 if (MONITOR_CPU_USAGE) {
3098 updateCpuStatsNow();
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003099 synchronized (mProcessStatsThread) {
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003100 cpuInfo = mProcessStats.printCurrentState(anrTime);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003101 }
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003102 info.append(processStats.printCurrentLoad());
Dan Egnor42471dd2010-01-07 17:25:22 -08003103 info.append(cpuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003104 }
3105
Dianne Hackborn6b1afeb2010-08-31 15:40:21 -07003106 info.append(processStats.printCurrentState(anrTime));
3107
Joe Onorato8a9b2202010-02-26 18:56:32 -08003108 Slog.e(TAG, info.toString());
Dan Egnor42471dd2010-01-07 17:25:22 -08003109 if (tracesFile == null) {
3110 // There is no trace file, so dump (only) the alleged culprit's threads to the log
3111 Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
3112 }
3113
Jeff Sharkeya353d262011-10-28 11:12:06 -07003114 addErrorToDropBox("anr", app, app.processName, activity, parent, annotation,
3115 cpuInfo, tracesFile, null);
Dan Egnor42471dd2010-01-07 17:25:22 -08003116
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003117 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003118 try {
Dan Egnor42471dd2010-01-07 17:25:22 -08003119 // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
3120 int res = mController.appNotResponding(app.processName, app.pid, info.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003121 if (res != 0) {
Dan Egnor42471dd2010-01-07 17:25:22 -08003122 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
3123 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003124 }
3125 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07003126 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003127 }
3128 }
3129
Dan Egnor42471dd2010-01-07 17:25:22 -08003130 // Unless configured otherwise, swallow ANRs in background processes & kill the process.
3131 boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
3132 Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003133
3134 synchronized (this) {
3135 if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07003136 Slog.w(TAG, "Killing " + app + ": background ANR");
3137 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
3138 app.processName, app.setAdj, "background ANR");
3139 Process.killProcessQuiet(app.pid);
Dianne Hackbornad5499d2010-03-29 18:08:45 -07003140 return;
3141 }
3142
3143 // Set the app's notResponding state, and look up the errorReportReceiver
3144 makeAppNotRespondingLocked(app,
3145 activity != null ? activity.shortComponentName : null,
3146 annotation != null ? "ANR " + annotation : "ANR",
3147 info.toString());
3148
3149 // Bring up the infamous App Not Responding dialog
3150 Message msg = Message.obtain();
3151 HashMap map = new HashMap();
3152 msg.what = SHOW_NOT_RESPONDING_MSG;
3153 msg.obj = map;
3154 map.put("app", app);
3155 if (activity != null) {
3156 map.put("activity", activity);
3157 }
3158
3159 mHandler.sendMessage(msg);
Dan Egnor42471dd2010-01-07 17:25:22 -08003160 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003161 }
3162
Dianne Hackborn0dad3642010-09-09 21:25:35 -07003163 final void showLaunchWarningLocked(final ActivityRecord cur, final ActivityRecord next) {
3164 if (!mLaunchWarningShown) {
3165 mLaunchWarningShown = true;
3166 mHandler.post(new Runnable() {
3167 @Override
3168 public void run() {
3169 synchronized (ActivityManagerService.this) {
3170 final Dialog d = new LaunchWarningWindow(mContext, cur, next);
3171 d.show();
3172 mHandler.postDelayed(new Runnable() {
3173 @Override
3174 public void run() {
3175 synchronized (ActivityManagerService.this) {
3176 d.dismiss();
3177 mLaunchWarningShown = false;
3178 }
3179 }
3180 }, 4000);
3181 }
3182 }
3183 });
3184 }
3185 }
3186
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003187 public boolean clearApplicationUserData(final String packageName,
3188 final IPackageDataObserver observer) {
3189 int uid = Binder.getCallingUid();
3190 int pid = Binder.getCallingPid();
3191 long callingId = Binder.clearCallingIdentity();
3192 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003193 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003194 int pkgUid = -1;
3195 synchronized(this) {
3196 try {
3197 pkgUid = pm.getPackageUid(packageName);
3198 } catch (RemoteException e) {
3199 }
3200 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003201 Slog.w(TAG, "Invalid packageName:" + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003202 return false;
3203 }
3204 if (uid == pkgUid || checkComponentPermission(
3205 android.Manifest.permission.CLEAR_APP_USER_DATA,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08003206 pid, uid, -1, true)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003207 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003208 forceStopPackageLocked(packageName, pkgUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003209 } else {
3210 throw new SecurityException(pid+" does not have permission:"+
3211 android.Manifest.permission.CLEAR_APP_USER_DATA+" to clear data" +
3212 "for process:"+packageName);
3213 }
3214 }
3215
3216 try {
3217 //clear application user data
3218 pm.clearApplicationUserData(packageName, observer);
3219 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
3220 Uri.fromParts("package", packageName, null));
3221 intent.putExtra(Intent.EXTRA_UID, pkgUid);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003222 broadcastIntentInPackage("android", Process.SYSTEM_UID, intent,
3223 null, null, 0, null, null, null, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003224 } catch (RemoteException e) {
3225 }
3226 } finally {
3227 Binder.restoreCallingIdentity(callingId);
3228 }
3229 return true;
3230 }
3231
Dianne Hackborn03abb812010-01-04 18:43:19 -08003232 public void killBackgroundProcesses(final String packageName) {
3233 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
3234 != PackageManager.PERMISSION_GRANTED &&
3235 checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
3236 != PackageManager.PERMISSION_GRANTED) {
3237 String msg = "Permission Denial: killBackgroundProcesses() from pid="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003238 + Binder.getCallingPid()
3239 + ", uid=" + Binder.getCallingUid()
Dianne Hackborn03abb812010-01-04 18:43:19 -08003240 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003241 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003242 throw new SecurityException(msg);
3243 }
3244
3245 long callingId = Binder.clearCallingIdentity();
3246 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003247 IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003248 int pkgUid = -1;
3249 synchronized(this) {
3250 try {
3251 pkgUid = pm.getPackageUid(packageName);
3252 } catch (RemoteException e) {
3253 }
3254 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003255 Slog.w(TAG, "Invalid packageName: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003256 return;
3257 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003258 killPackageProcessesLocked(packageName, pkgUid,
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08003259 ProcessList.SERVICE_ADJ, false, true, true, false, "kill background");
3260 }
3261 } finally {
3262 Binder.restoreCallingIdentity(callingId);
3263 }
3264 }
3265
3266 public void killAllBackgroundProcesses() {
3267 if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
3268 != PackageManager.PERMISSION_GRANTED) {
3269 String msg = "Permission Denial: killAllBackgroundProcesses() from pid="
3270 + Binder.getCallingPid()
3271 + ", uid=" + Binder.getCallingUid()
3272 + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
3273 Slog.w(TAG, msg);
3274 throw new SecurityException(msg);
3275 }
3276
3277 long callingId = Binder.clearCallingIdentity();
3278 try {
3279 synchronized(this) {
3280 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
3281 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
3282 final int NA = apps.size();
3283 for (int ia=0; ia<NA; ia++) {
3284 ProcessRecord app = apps.valueAt(ia);
3285 if (app.persistent) {
3286 // we don't kill persistent processes
3287 continue;
3288 }
3289 if (app.removed) {
3290 procs.add(app);
3291 } else if (app.setAdj >= ProcessList.HIDDEN_APP_MIN_ADJ) {
3292 app.removed = true;
3293 procs.add(app);
3294 }
3295 }
3296 }
3297
3298 int N = procs.size();
3299 for (int i=0; i<N; i++) {
3300 removeProcessLocked(procs.get(i), false, true, "kill all background");
3301 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003302 }
3303 } finally {
3304 Binder.restoreCallingIdentity(callingId);
3305 }
3306 }
3307
3308 public void forceStopPackage(final String packageName) {
3309 if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
3310 != PackageManager.PERMISSION_GRANTED) {
3311 String msg = "Permission Denial: forceStopPackage() from pid="
3312 + Binder.getCallingPid()
3313 + ", uid=" + Binder.getCallingUid()
3314 + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003315 Slog.w(TAG, msg);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003316 throw new SecurityException(msg);
3317 }
3318
3319 long callingId = Binder.clearCallingIdentity();
3320 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003321 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn03abb812010-01-04 18:43:19 -08003322 int pkgUid = -1;
3323 synchronized(this) {
3324 try {
3325 pkgUid = pm.getPackageUid(packageName);
3326 } catch (RemoteException e) {
3327 }
3328 if (pkgUid == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003329 Slog.w(TAG, "Invalid packageName: " + packageName);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003330 return;
3331 }
3332 forceStopPackageLocked(packageName, pkgUid);
Dianne Hackborne7f97212011-02-24 14:40:20 -08003333 try {
3334 pm.setPackageStoppedState(packageName, true);
3335 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08003336 } catch (IllegalArgumentException e) {
3337 Slog.w(TAG, "Failed trying to unstop package "
3338 + packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08003339 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003340 }
3341 } finally {
3342 Binder.restoreCallingIdentity(callingId);
3343 }
3344 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003345
3346 /*
3347 * The pkg name and uid have to be specified.
3348 * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
3349 */
3350 public void killApplicationWithUid(String pkg, int uid) {
3351 if (pkg == null) {
3352 return;
3353 }
3354 // Make sure the uid is valid.
3355 if (uid < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003356 Slog.w(TAG, "Invalid uid specified for pkg : " + pkg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003357 return;
3358 }
3359 int callerUid = Binder.getCallingUid();
3360 // Only the system server can kill an application
3361 if (callerUid == Process.SYSTEM_UID) {
Suchi Amalapurapud9d25762009-08-17 16:57:03 -07003362 // Post an aysnc message to kill the application
3363 Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
3364 msg.arg1 = uid;
3365 msg.arg2 = 0;
3366 msg.obj = pkg;
Suchi Amalapurapud50066f2009-08-18 16:57:41 -07003367 mHandler.sendMessage(msg);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003368 } else {
3369 throw new SecurityException(callerUid + " cannot kill pkg: " +
3370 pkg);
3371 }
3372 }
3373
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003374 public void closeSystemDialogs(String reason) {
3375 Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003376 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003377 if (reason != null) {
3378 intent.putExtra("reason", reason);
3379 }
3380
3381 final int uid = Binder.getCallingUid();
3382 final long origId = Binder.clearCallingIdentity();
3383 synchronized (this) {
3384 int i = mWatchers.beginBroadcast();
3385 while (i > 0) {
3386 i--;
3387 IActivityWatcher w = mWatchers.getBroadcastItem(i);
3388 if (w != null) {
3389 try {
3390 w.closingSystemDialogs(reason);
3391 } catch (RemoteException e) {
3392 }
3393 }
3394 }
3395 mWatchers.finishBroadcast();
3396
Dianne Hackbornffa42482009-09-23 22:20:11 -07003397 mWindowManager.closeSystemDialogs(reason);
3398
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003399 for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
3400 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackbornffa42482009-09-23 22:20:11 -07003401 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003402 r.stack.finishActivityLocked(r, i,
Dianne Hackbornffa42482009-09-23 22:20:11 -07003403 Activity.RESULT_CANCELED, null, "close-sys");
3404 }
3405 }
3406
Dianne Hackborna6ddc8a2009-07-28 17:49:55 -07003407 broadcastIntentLocked(null, null, intent, null,
3408 null, 0, null, null, null, false, false, -1, uid);
3409 }
3410 Binder.restoreCallingIdentity(origId);
3411 }
3412
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003413 public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003414 throws RemoteException {
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003415 Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
3416 for (int i=pids.length-1; i>=0; i--) {
3417 infos[i] = new Debug.MemoryInfo();
3418 Debug.getMemoryInfo(pids[i], infos[i]);
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003419 }
Dianne Hackborn4f21c4c2009-09-17 10:24:05 -07003420 return infos;
Dianne Hackborn3025ef32009-08-31 21:31:47 -07003421 }
Christopher Tate5e1ab332009-09-01 20:32:49 -07003422
Dianne Hackbornb437e092011-08-05 17:50:29 -07003423 public long[] getProcessPss(int[] pids) throws RemoteException {
3424 long[] pss = new long[pids.length];
3425 for (int i=pids.length-1; i>=0; i--) {
3426 pss[i] = Debug.getPss(pids[i]);
3427 }
3428 return pss;
3429 }
3430
Christopher Tate5e1ab332009-09-01 20:32:49 -07003431 public void killApplicationProcess(String processName, int uid) {
3432 if (processName == null) {
3433 return;
3434 }
3435
3436 int callerUid = Binder.getCallingUid();
3437 // Only the system server can kill an application
3438 if (callerUid == Process.SYSTEM_UID) {
3439 synchronized (this) {
3440 ProcessRecord app = getProcessRecordLocked(processName, uid);
Christopher Tate4a627c72011-04-01 14:43:32 -07003441 if (app != null && app.thread != null) {
Christopher Tate5e1ab332009-09-01 20:32:49 -07003442 try {
3443 app.thread.scheduleSuicide();
3444 } catch (RemoteException e) {
3445 // If the other end already died, then our work here is done.
3446 }
3447 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003448 Slog.w(TAG, "Process/uid not found attempting kill of "
Christopher Tate5e1ab332009-09-01 20:32:49 -07003449 + processName + " / " + uid);
3450 }
3451 }
3452 } else {
3453 throw new SecurityException(callerUid + " cannot kill app process: " +
3454 processName);
3455 }
3456 }
3457
Dianne Hackborn03abb812010-01-04 18:43:19 -08003458 private void forceStopPackageLocked(final String packageName, int uid) {
Christopher Tate3dacd842011-08-19 14:56:15 -07003459 forceStopPackageLocked(packageName, uid, false, false, true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003460 Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
3461 Uri.fromParts("package", packageName, null));
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003462 if (!mProcessesReady) {
3463 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
3464 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003465 intent.putExtra(Intent.EXTRA_UID, uid);
3466 broadcastIntentLocked(null, null, intent,
3467 null, null, 0, null, null, null,
3468 false, false, MY_PID, Process.SYSTEM_UID);
3469 }
3470
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003471 private final boolean killPackageProcessesLocked(String packageName, int uid,
Christopher Tate3dacd842011-08-19 14:56:15 -07003472 int minOomAdj, boolean callerWillRestart, boolean allowRestart, boolean doit,
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08003473 boolean evenPersistent, String reason) {
Dianne Hackborn03abb812010-01-04 18:43:19 -08003474 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003475
Dianne Hackborn03abb812010-01-04 18:43:19 -08003476 // Remove all processes this package may have touched: all with the
3477 // same UID (except for the system or root user), and all whose name
3478 // matches the package name.
3479 final String procNamePrefix = packageName + ":";
3480 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
3481 final int NA = apps.size();
3482 for (int ia=0; ia<NA; ia++) {
3483 ProcessRecord app = apps.valueAt(ia);
Christopher Tate3dacd842011-08-19 14:56:15 -07003484 if (app.persistent && !evenPersistent) {
Christopher Tate064d8422011-07-26 15:38:07 -07003485 // we don't kill persistent processes
3486 continue;
3487 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003488 if (app.removed) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003489 if (doit) {
3490 procs.add(app);
3491 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003492 } else if ((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
3493 || app.processName.equals(packageName)
3494 || app.processName.startsWith(procNamePrefix)) {
3495 if (app.setAdj >= minOomAdj) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003496 if (!doit) {
3497 return true;
3498 }
Dianne Hackborn03abb812010-01-04 18:43:19 -08003499 app.removed = true;
3500 procs.add(app);
3501 }
3502 }
3503 }
3504 }
3505
3506 int N = procs.size();
3507 for (int i=0; i<N; i++) {
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08003508 removeProcessLocked(procs.get(i), callerWillRestart, allowRestart, reason);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003509 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003510 return N > 0;
Dianne Hackborn03abb812010-01-04 18:43:19 -08003511 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003512
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003513 private final boolean forceStopPackageLocked(String name, int uid,
Christopher Tate3dacd842011-08-19 14:56:15 -07003514 boolean callerWillRestart, boolean purgeCache, boolean doit,
3515 boolean evenPersistent) {
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07003516 int i;
3517 int N;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003518
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003519 if (uid < 0) {
3520 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07003521 uid = AppGlobals.getPackageManager().getPackageUid(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003522 } catch (RemoteException e) {
3523 }
3524 }
3525
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003526 if (doit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003527 Slog.i(TAG, "Force stopping package " + name + " uid=" + uid);
Dianne Hackborn03abb812010-01-04 18:43:19 -08003528
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003529 Iterator<SparseArray<Long>> badApps = mProcessCrashTimes.getMap().values().iterator();
3530 while (badApps.hasNext()) {
3531 SparseArray<Long> ba = badApps.next();
3532 if (ba.get(uid) != null) {
3533 badApps.remove();
3534 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003535 }
3536 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003537
3538 boolean didSomething = killPackageProcessesLocked(name, uid, -100,
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08003539 callerWillRestart, false, doit, evenPersistent, "force stop");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003540
Dianne Hackborne5ba16a2011-09-09 12:35:29 -07003541 TaskRecord lastTask = null;
3542 for (i=0; i<mMainStack.mHistory.size(); i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003543 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackborne5ba16a2011-09-09 12:35:29 -07003544 final boolean samePackage = r.packageName.equals(name);
3545 if ((samePackage || r.task == lastTask)
Christopher Tate3dacd842011-08-19 14:56:15 -07003546 && (r.app == null || evenPersistent || !r.app.persistent)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003547 if (!doit) {
Dianne Hackborn80a7ac12011-09-22 18:32:52 -07003548 if (r.finishing) {
3549 // If this activity is just finishing, then it is not
3550 // interesting as far as something to stop.
3551 continue;
3552 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003553 return true;
3554 }
3555 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003556 Slog.i(TAG, " Force finishing activity " + r);
Dianne Hackborne5ba16a2011-09-09 12:35:29 -07003557 if (samePackage) {
3558 if (r.app != null) {
3559 r.app.removed = true;
3560 }
3561 r.app = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003562 }
Dianne Hackborne5ba16a2011-09-09 12:35:29 -07003563 lastTask = r.task;
3564 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
3565 null, "force-stop")) {
3566 i--;
3567 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003568 }
3569 }
3570
3571 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
3572 for (ServiceRecord service : mServices.values()) {
Christopher Tate064d8422011-07-26 15:38:07 -07003573 if (service.packageName.equals(name)
Christopher Tate3dacd842011-08-19 14:56:15 -07003574 && (service.app == null || evenPersistent || !service.app.persistent)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003575 if (!doit) {
3576 return true;
3577 }
3578 didSomething = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003579 Slog.i(TAG, " Force stopping service " + service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003580 if (service.app != null) {
3581 service.app.removed = true;
3582 }
3583 service.app = null;
3584 services.add(service);
3585 }
3586 }
3587
3588 N = services.size();
3589 for (i=0; i<N; i++) {
3590 bringDownServiceLocked(services.get(i), true);
3591 }
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07003592
3593 ArrayList<ContentProviderRecord> providers = new ArrayList<ContentProviderRecord>();
3594 for (ContentProviderRecord provider : mProvidersByClass.values()) {
3595 if (provider.info.packageName.equals(name)
3596 && (provider.proc == null || evenPersistent || !provider.proc.persistent)) {
3597 if (!doit) {
3598 return true;
3599 }
3600 didSomething = true;
3601 providers.add(provider);
3602 }
3603 }
3604
3605 N = providers.size();
3606 for (i=0; i<N; i++) {
3607 removeDyingProviderLocked(null, providers.get(i));
3608 }
3609
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003610 if (doit) {
3611 if (purgeCache) {
3612 AttributeCache ac = AttributeCache.instance();
3613 if (ac != null) {
3614 ac.removePackage(name);
3615 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003616 }
Dianne Hackborn38cc8962011-10-13 11:33:55 -07003617 if (mBooted) {
3618 mMainStack.resumeTopActivityLocked(null);
3619 mMainStack.scheduleIdleLocked();
3620 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003621 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08003622
3623 return didSomething;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003624 }
3625
Dianne Hackborn130b0d22011-07-26 22:07:48 -07003626 private final boolean removeProcessLocked(ProcessRecord app,
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08003627 boolean callerWillRestart, boolean allowRestart, String reason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003628 final String name = app.processName;
3629 final int uid = app.info.uid;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003630 if (DEBUG_PROCESSES) Slog.d(
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08003631 TAG, "Force removing proc " + app.toShortString() + " (" + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003632 + "/" + uid + ")");
3633
3634 mProcessNames.remove(name, uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003635 if (mHeavyWeightProcess == app) {
3636 mHeavyWeightProcess = null;
3637 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3638 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003639 boolean needRestart = false;
3640 if (app.pid > 0 && app.pid != MY_PID) {
3641 int pid = app.pid;
3642 synchronized (mPidsSelfLocked) {
3643 mPidsSelfLocked.remove(pid);
3644 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3645 }
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08003646 Slog.i(TAG, "Killing proc " + app.toShortString() + ": " + reason);
Dianne Hackborn130b0d22011-07-26 22:07:48 -07003647 handleAppDiedLocked(app, true, allowRestart);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003648 mLruProcesses.remove(app);
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08003649 Process.killProcessQuiet(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003650
3651 if (app.persistent) {
3652 if (!callerWillRestart) {
3653 addAppLocked(app.info);
3654 } else {
3655 needRestart = true;
3656 }
3657 }
3658 } else {
3659 mRemovedProcesses.add(app);
3660 }
3661
3662 return needRestart;
3663 }
3664
3665 private final void processStartTimedOutLocked(ProcessRecord app) {
3666 final int pid = app.pid;
3667 boolean gone = false;
3668 synchronized (mPidsSelfLocked) {
3669 ProcessRecord knownApp = mPidsSelfLocked.get(pid);
3670 if (knownApp != null && knownApp.thread == null) {
3671 mPidsSelfLocked.remove(pid);
3672 gone = true;
3673 }
3674 }
3675
3676 if (gone) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003677 Slog.w(TAG, "Process " + app + " failed to attach");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003678 EventLog.writeEvent(EventLogTags.AM_PROCESS_START_TIMEOUT, pid, app.info.uid,
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003679 app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003680 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -07003681 if (mHeavyWeightProcess == app) {
3682 mHeavyWeightProcess = null;
3683 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
3684 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003685 // Take care of any launching providers waiting for this process.
3686 checkAppInLaunchingProvidersLocked(app, true);
3687 // Take care of any services that are waiting for the process.
3688 for (int i=0; i<mPendingServices.size(); i++) {
3689 ServiceRecord sr = mPendingServices.get(i);
3690 if (app.info.uid == sr.appInfo.uid
3691 && app.processName.equals(sr.processName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003692 Slog.w(TAG, "Forcing bringing down service: " + sr);
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003693 mPendingServices.remove(i);
3694 i--;
3695 bringDownServiceLocked(sr, true);
3696 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003697 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07003698 EventLog.writeEvent(EventLogTags.AM_KILL, pid,
3699 app.processName, app.setAdj, "start timeout");
3700 Process.killProcessQuiet(pid);
Christopher Tate181fafa2009-05-14 11:12:14 -07003701 if (mBackupTarget != null && mBackupTarget.app.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003702 Slog.w(TAG, "Unattached app died before backup, skipping");
Christopher Tate181fafa2009-05-14 11:12:14 -07003703 try {
3704 IBackupManager bm = IBackupManager.Stub.asInterface(
3705 ServiceManager.getService(Context.BACKUP_SERVICE));
3706 bm.agentDisconnected(app.info.packageName);
3707 } catch (RemoteException e) {
3708 // Can't happen; the backup manager is local
3709 }
3710 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003711 if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003712 Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003713 mPendingBroadcast.state = BroadcastRecord.IDLE;
3714 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
Dianne Hackbornf670ef72009-11-16 13:59:16 -08003715 mPendingBroadcast = null;
3716 scheduleBroadcastsLocked();
3717 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003718 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003719 Slog.w(TAG, "Spurious process start timeout - pid not known for " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003720 }
3721 }
3722
3723 private final boolean attachApplicationLocked(IApplicationThread thread,
3724 int pid) {
3725
3726 // Find the application record that is being attached... either via
3727 // the pid if we are running in multiple processes, or just pull the
3728 // next app record if we are emulating process with anonymous threads.
3729 ProcessRecord app;
3730 if (pid != MY_PID && pid >= 0) {
3731 synchronized (mPidsSelfLocked) {
3732 app = mPidsSelfLocked.get(pid);
3733 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003734 } else {
3735 app = null;
3736 }
3737
3738 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003739 Slog.w(TAG, "No pending application record for pid " + pid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003740 + " (IApplicationThread " + thread + "); dropping process");
Doug Zongker2bec3d42009-12-04 12:52:44 -08003741 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003742 if (pid > 0 && pid != MY_PID) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07003743 Process.killProcessQuiet(pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003744 } else {
3745 try {
3746 thread.scheduleExit();
3747 } catch (Exception e) {
3748 // Ignore exceptions.
3749 }
3750 }
3751 return false;
3752 }
3753
3754 // If this application record is still attached to a previous
3755 // process, clean it up now.
3756 if (app.thread != null) {
Dianne Hackborn130b0d22011-07-26 22:07:48 -07003757 handleAppDiedLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003758 }
3759
3760 // Tell the process all about itself.
3761
Joe Onorato8a9b2202010-02-26 18:56:32 -08003762 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003763 TAG, "Binding process pid " + pid + " to record " + app);
3764
3765 String processName = app.processName;
3766 try {
Dianne Hackborn1b64e0d2011-07-17 15:23:59 -07003767 AppDeathRecipient adr = new AppDeathRecipient(
3768 app, pid, thread);
3769 thread.asBinder().linkToDeath(adr, 0);
3770 app.deathRecipient = adr;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003771 } catch (RemoteException e) {
3772 app.resetPackageList();
3773 startProcessLocked(app, "link fail", processName);
3774 return false;
3775 }
3776
Doug Zongker2bec3d42009-12-04 12:52:44 -08003777 EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003778
3779 app.thread = thread;
3780 app.curAdj = app.setAdj = -100;
Dianne Hackborn09c916b2009-12-08 14:50:51 -08003781 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
3782 app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003783 app.forcingToForeground = null;
3784 app.foregroundServices = false;
Dianne Hackbornf0754f5b2011-07-21 16:02:07 -07003785 app.hasShownUi = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003786 app.debugging = false;
3787
3788 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
3789
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003790 boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003791 List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003792
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003793 if (!normalMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003794 Slog.i(TAG, "Launching preboot mode app: " + app);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003795 }
3796
Joe Onorato8a9b2202010-02-26 18:56:32 -08003797 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003798 TAG, "New app record " + app
3799 + " thread=" + thread.asBinder() + " pid=" + pid);
3800 try {
3801 int testMode = IApplicationThread.DEBUG_OFF;
3802 if (mDebugApp != null && mDebugApp.equals(processName)) {
3803 testMode = mWaitForDebugger
3804 ? IApplicationThread.DEBUG_WAIT
3805 : IApplicationThread.DEBUG_ON;
3806 app.debugging = true;
3807 if (mDebugTransient) {
3808 mDebugApp = mOrigDebugApp;
3809 mWaitForDebugger = mOrigWaitForDebugger;
3810 }
3811 }
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07003812 String profileFile = app.instrumentationProfileFile;
3813 ParcelFileDescriptor profileFd = null;
3814 boolean profileAutoStop = false;
3815 if (mProfileApp != null && mProfileApp.equals(processName)) {
3816 mProfileProc = app;
3817 profileFile = mProfileFile;
3818 profileFd = mProfileFd;
3819 profileAutoStop = mAutoStopProfiler;
3820 }
3821
Christopher Tate181fafa2009-05-14 11:12:14 -07003822 // If the app is being launched for restore or full backup, set it up specially
3823 boolean isRestrictedBackupMode = false;
3824 if (mBackupTarget != null && mBackupAppName.equals(processName)) {
3825 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
Christopher Tate75a99702011-05-18 16:28:19 -07003826 || (mBackupTarget.backupMode == BackupRecord.RESTORE_FULL)
Christopher Tate181fafa2009-05-14 11:12:14 -07003827 || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
3828 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003829
Dianne Hackbornd7f6daa2009-06-22 17:06:35 -07003830 ensurePackageDexOpt(app.instrumentationInfo != null
3831 ? app.instrumentationInfo.packageName
3832 : app.info.packageName);
3833 if (app.instrumentationClass != null) {
3834 ensurePackageDexOpt(app.instrumentationClass.getPackageName());
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003835 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003836 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -07003837 + processName + " with config " + mConfiguration);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04003838 ApplicationInfo appInfo = app.instrumentationInfo != null
3839 ? app.instrumentationInfo : app.info;
Dianne Hackborn8ea5e1d2011-05-27 16:45:31 -07003840 app.compat = compatibilityInfoForPackageLocked(appInfo);
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07003841 if (profileFd != null) {
3842 profileFd = profileFd.dup();
3843 }
Dianne Hackborne2515ee2011-04-27 18:52:56 -04003844 thread.bindApplication(processName, appInfo, providers,
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07003845 app.instrumentationClass, profileFile, profileFd, profileAutoStop,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003846 app.instrumentationArguments, app.instrumentationWatcher, testMode,
Dianne Hackborn5d927c22011-09-02 12:22:18 -07003847 isRestrictedBackupMode || !normalMode, app.persistent,
Dianne Hackborn813075a62011-11-14 17:45:19 -08003848 new Configuration(mConfiguration), app.compat, getCommonServicesLocked(),
Svetoslav Ganov54d068e2011-03-02 12:58:40 -08003849 mCoreSettingsObserver.getCoreSettingsLocked());
Dianne Hackborndd71fc82009-12-16 19:24:32 -08003850 updateLruProcessLocked(app, false, true);
Dianne Hackbornfd12af42009-08-27 00:44:33 -07003851 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003852 } catch (Exception e) {
3853 // todo: Yikes! What should we do? For now we will try to
3854 // start another process, but that could easily get us in
3855 // an infinite loop of restarting processes...
Joe Onorato8a9b2202010-02-26 18:56:32 -08003856 Slog.w(TAG, "Exception thrown during bind!", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003857
3858 app.resetPackageList();
Dianne Hackborn1b64e0d2011-07-17 15:23:59 -07003859 app.unlinkDeathRecipient();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003860 startProcessLocked(app, "bind fail", processName);
3861 return false;
3862 }
3863
3864 // Remove this record from the list of starting applications.
3865 mPersistentStartingProcesses.remove(app);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07003866 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
3867 "Attach application locked removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003868 mProcessesOnHold.remove(app);
3869
3870 boolean badApp = false;
3871 boolean didSomething = false;
3872
3873 // See if the top visible activity is waiting to run in this process...
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003874 ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
Christopher Tate04c0af82010-06-07 18:35:20 -07003875 if (hr != null && normalMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003876 if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
3877 && processName.equals(hr.processName)) {
3878 try {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003879 if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003880 didSomething = true;
3881 }
3882 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003883 Slog.w(TAG, "Exception in new application when starting activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003884 + hr.intent.getComponent().flattenToShortString(), e);
3885 badApp = true;
3886 }
3887 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07003888 mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003889 }
3890 }
3891
3892 // Find any services that should be running in this process...
3893 if (!badApp && mPendingServices.size() > 0) {
3894 ServiceRecord sr = null;
3895 try {
3896 for (int i=0; i<mPendingServices.size(); i++) {
3897 sr = mPendingServices.get(i);
3898 if (app.info.uid != sr.appInfo.uid
3899 || !processName.equals(sr.processName)) {
3900 continue;
3901 }
3902
3903 mPendingServices.remove(i);
3904 i--;
3905 realStartServiceLocked(sr, app);
3906 didSomething = true;
3907 }
3908 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003909 Slog.w(TAG, "Exception in new application when starting service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003910 + sr.shortName, e);
3911 badApp = true;
3912 }
3913 }
3914
3915 // Check if the next broadcast receiver is in this process...
3916 BroadcastRecord br = mPendingBroadcast;
3917 if (!badApp && br != null && br.curApp == app) {
3918 try {
3919 mPendingBroadcast = null;
3920 processCurBroadcastLocked(br, app);
3921 didSomething = true;
3922 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003923 Slog.w(TAG, "Exception in new application when starting receiver "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003924 + br.curComponent.flattenToShortString(), e);
3925 badApp = true;
Jeff Brown4d94a762010-09-23 11:33:28 -07003926 logBroadcastReceiverDiscardLocked(br);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003927 finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
3928 br.resultExtras, br.resultAbort, true);
3929 scheduleBroadcastsLocked();
Magnus Edlund7bb25812010-02-24 15:45:06 +01003930 // We need to reset the state if we fails to start the receiver.
3931 br.state = BroadcastRecord.IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003932 }
3933 }
3934
Christopher Tate181fafa2009-05-14 11:12:14 -07003935 // Check whether the next backup agent is in this process...
3936 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.info.uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003937 if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003938 ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
Christopher Tate181fafa2009-05-14 11:12:14 -07003939 try {
Dianne Hackborne2515ee2011-04-27 18:52:56 -04003940 thread.scheduleCreateBackupAgent(mBackupTarget.appInfo,
3941 compatibilityInfoForPackageLocked(mBackupTarget.appInfo),
3942 mBackupTarget.backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -07003943 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003944 Slog.w(TAG, "Exception scheduling backup agent creation: ");
Christopher Tate181fafa2009-05-14 11:12:14 -07003945 e.printStackTrace();
3946 }
3947 }
3948
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003949 if (badApp) {
3950 // todo: Also need to kill application to deal with all
3951 // kinds of exceptions.
Dianne Hackborn130b0d22011-07-26 22:07:48 -07003952 handleAppDiedLocked(app, false, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003953 return false;
3954 }
3955
3956 if (!didSomething) {
3957 updateOomAdjLocked();
3958 }
3959
3960 return true;
3961 }
3962
3963 public final void attachApplication(IApplicationThread thread) {
3964 synchronized (this) {
3965 int callingPid = Binder.getCallingPid();
3966 final long origId = Binder.clearCallingIdentity();
3967 attachApplicationLocked(thread, callingPid);
3968 Binder.restoreCallingIdentity(origId);
3969 }
3970 }
3971
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07003972 public final void activityIdle(IBinder token, Configuration config, boolean stopProfiling) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003973 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07003974 ActivityRecord r = mMainStack.activityIdleInternal(token, false, config);
3975 if (stopProfiling) {
3976 synchronized (this) {
3977 if (mProfileProc == r.app) {
3978 if (mProfileFd != null) {
3979 try {
3980 mProfileFd.close();
3981 } catch (IOException e) {
3982 }
3983 clearProfilerLocked();
3984 }
3985 }
3986 }
3987 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003988 Binder.restoreCallingIdentity(origId);
3989 }
3990
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003991 void enableScreenAfterBoot() {
Doug Zongker2bec3d42009-12-04 12:52:44 -08003992 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
Dianne Hackborn9acc0302009-08-25 00:27:12 -07003993 SystemClock.uptimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003994 mWindowManager.enableScreenAfterBoot();
3995 }
3996
Dianne Hackborn661cd522011-08-22 00:26:20 -07003997 public void showBootMessage(final CharSequence msg, final boolean always) {
3998 mWindowManager.showBootMessage(msg, always);
3999 }
4000
Dianne Hackborn90c52de2011-09-23 12:57:44 -07004001 public void dismissKeyguardOnNextActivity() {
4002 synchronized (this) {
4003 mMainStack.dismissKeyguardOnNextActivityLocked();
4004 }
4005 }
4006
Dianne Hackborn9acc0302009-08-25 00:27:12 -07004007 final void finishBooting() {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004008 IntentFilter pkgFilter = new IntentFilter();
4009 pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
4010 pkgFilter.addDataScheme("package");
4011 mContext.registerReceiver(new BroadcastReceiver() {
4012 @Override
4013 public void onReceive(Context context, Intent intent) {
4014 String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
4015 if (pkgs != null) {
4016 for (String pkg : pkgs) {
Vairavan Srinivasan61f07652010-07-22 13:36:40 -07004017 synchronized (ActivityManagerService.this) {
Christopher Tate3dacd842011-08-19 14:56:15 -07004018 if (forceStopPackageLocked(pkg, -1, false, false, false, false)) {
Vairavan Srinivasan61f07652010-07-22 13:36:40 -07004019 setResultCode(Activity.RESULT_OK);
4020 return;
4021 }
4022 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004023 }
4024 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07004025 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004026 }, pkgFilter);
4027
4028 synchronized (this) {
4029 // Ensure that any processes we had put on hold are now started
4030 // up.
4031 final int NP = mProcessesOnHold.size();
4032 if (NP > 0) {
4033 ArrayList<ProcessRecord> procs =
4034 new ArrayList<ProcessRecord>(mProcessesOnHold);
4035 for (int ip=0; ip<NP; ip++) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07004036 if (DEBUG_PROCESSES) Slog.v(TAG, "Starting process on hold: "
4037 + procs.get(ip));
4038 startProcessLocked(procs.get(ip), "on-hold", null);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004039 }
4040 }
4041
4042 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07004043 // Start looking for apps that are abusing wake locks.
4044 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07004045 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08004046 // Tell anyone interested that we are done booting!
Dianne Hackbornf4c454b2010-08-11 12:47:41 -07004047 SystemProperties.set("sys.boot_completed", "1");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07004048 broadcastIntentLocked(null, null,
4049 new Intent(Intent.ACTION_BOOT_COMPLETED, null),
4050 null, null, 0, null, null,
4051 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
4052 false, false, MY_PID, Process.SYSTEM_UID);
4053 }
4054 }
4055 }
4056
4057 final void ensureBootCompleted() {
4058 boolean booting;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004059 boolean enableScreen;
4060 synchronized (this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07004061 booting = mBooting;
4062 mBooting = false;
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004063 enableScreen = !mBooted;
4064 mBooted = true;
4065 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07004066
4067 if (booting) {
4068 finishBooting();
4069 }
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004070
4071 if (enableScreen) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07004072 enableScreenAfterBoot();
4073 }
4074 }
4075
Dianne Hackborn0aae2d42010-12-07 23:51:29 -08004076 public final void activityPaused(IBinder token) {
4077 final long origId = Binder.clearCallingIdentity();
4078 mMainStack.activityPaused(token, false);
4079 Binder.restoreCallingIdentity(origId);
4080 }
4081
4082 public final void activityStopped(IBinder token, Bundle icicle, Bitmap thumbnail,
4083 CharSequence description) {
4084 if (localLOGV) Slog.v(
4085 TAG, "Activity stopped: token=" + token);
4086
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004087 // Refuse possible leaked file descriptors
4088 if (icicle != null && icicle.hasFileDescriptors()) {
4089 throw new IllegalArgumentException("File descriptors passed in Bundle");
4090 }
4091
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004092 ActivityRecord r = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004093
4094 final long origId = Binder.clearCallingIdentity();
4095
4096 synchronized (this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004097 r = mMainStack.isInStackLocked(token);
4098 if (r != null) {
4099 r.stack.activityStoppedLocked(r, icicle, thumbnail, description);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004100 }
4101 }
4102
4103 if (r != null) {
4104 sendPendingThumbnail(r, null, null, null, false);
4105 }
4106
4107 trimApplications();
4108
4109 Binder.restoreCallingIdentity(origId);
4110 }
4111
4112 public final void activityDestroyed(IBinder token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004113 if (DEBUG_SWITCH) Slog.v(TAG, "ACTIVITY DESTROYED: " + token);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004114 mMainStack.activityDestroyed(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004115 }
4116
4117 public String getCallingPackage(IBinder token) {
4118 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004119 ActivityRecord r = getCallingRecordLocked(token);
Dianne Hackborn9bbcb912009-10-20 15:42:38 -07004120 return r != null && r.app != null ? r.info.packageName : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004121 }
4122 }
4123
4124 public ComponentName getCallingActivity(IBinder token) {
4125 synchronized (this) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004126 ActivityRecord r = getCallingRecordLocked(token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004127 return r != null ? r.intent.getComponent() : null;
4128 }
4129 }
4130
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004131 private ActivityRecord getCallingRecordLocked(IBinder token) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004132 ActivityRecord r = mMainStack.isInStackLocked(token);
4133 if (r == null) {
4134 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004135 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004136 return r.resultTo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004137 }
4138
4139 public ComponentName getActivityClassForToken(IBinder token) {
4140 synchronized(this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004141 ActivityRecord r = mMainStack.isInStackLocked(token);
4142 if (r == null) {
4143 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004144 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004145 return r.intent.getComponent();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004146 }
4147 }
4148
4149 public String getPackageForToken(IBinder token) {
4150 synchronized(this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004151 ActivityRecord r = mMainStack.isInStackLocked(token);
4152 if (r == null) {
4153 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004154 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004155 return r.packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004156 }
4157 }
4158
4159 public IIntentSender getIntentSender(int type,
4160 String packageName, IBinder token, String resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004161 int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004162 // Refuse possible leaked file descriptors
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004163 if (intents != null) {
4164 if (intents.length < 1) {
4165 throw new IllegalArgumentException("Intents array length must be >= 1");
4166 }
4167 for (int i=0; i<intents.length; i++) {
4168 Intent intent = intents[i];
Dianne Hackborn52b0ce02011-04-14 13:09:32 -07004169 if (intent != null) {
4170 if (intent.hasFileDescriptors()) {
4171 throw new IllegalArgumentException("File descriptors passed in Intent");
4172 }
4173 if (type == INTENT_SENDER_BROADCAST &&
4174 (intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
4175 throw new IllegalArgumentException(
4176 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
4177 }
4178 intents[i] = new Intent(intent);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004179 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004180 }
4181 if (resolvedTypes != null && resolvedTypes.length != intents.length) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07004182 throw new IllegalArgumentException(
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004183 "Intent array length does not match resolvedTypes length");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07004184 }
4185 }
4186
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004187 synchronized(this) {
4188 int callingUid = Binder.getCallingUid();
4189 try {
Jeff Brown10e89712011-07-08 18:52:57 -07004190 if (callingUid != 0 && callingUid != Process.SYSTEM_UID) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004191 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004192 .getPackageUid(packageName);
4193 if (uid != Binder.getCallingUid()) {
4194 String msg = "Permission Denial: getIntentSender() from pid="
4195 + Binder.getCallingPid()
4196 + ", uid=" + Binder.getCallingUid()
4197 + ", (need uid=" + uid + ")"
4198 + " is not allowed to send as package " + packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004199 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004200 throw new SecurityException(msg);
4201 }
4202 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004203
4204 return getIntentSenderLocked(type, packageName, callingUid,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004205 token, resultWho, requestCode, intents, resolvedTypes, flags);
Dianne Hackborn860755f2010-06-03 18:47:52 -07004206
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004207 } catch (RemoteException e) {
4208 throw new SecurityException(e);
4209 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004210 }
4211 }
4212
4213 IIntentSender getIntentSenderLocked(int type,
4214 String packageName, int callingUid, IBinder token, String resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004215 int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004216 ActivityRecord activity = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004217 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004218 activity = mMainStack.isInStackLocked(token);
4219 if (activity == null) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07004220 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004221 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004222 if (activity.finishing) {
4223 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004224 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004225 }
4226
4227 final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
4228 final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
4229 final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
4230 flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
4231 |PendingIntent.FLAG_UPDATE_CURRENT);
4232
4233 PendingIntentRecord.Key key = new PendingIntentRecord.Key(
4234 type, packageName, activity, resultWho,
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004235 requestCode, intents, resolvedTypes, flags);
Dianne Hackborn860755f2010-06-03 18:47:52 -07004236 WeakReference<PendingIntentRecord> ref;
4237 ref = mIntentSenderRecords.get(key);
4238 PendingIntentRecord rec = ref != null ? ref.get() : null;
4239 if (rec != null) {
4240 if (!cancelCurrent) {
4241 if (updateCurrent) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08004242 if (rec.key.requestIntent != null) {
4243 rec.key.requestIntent.replaceExtras(intents != null ? intents[0] : null);
4244 }
4245 if (intents != null) {
4246 intents[intents.length-1] = rec.key.requestIntent;
4247 rec.key.allIntents = intents;
4248 rec.key.allResolvedTypes = resolvedTypes;
4249 } else {
4250 rec.key.allIntents = null;
4251 rec.key.allResolvedTypes = null;
4252 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004253 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004254 return rec;
4255 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004256 rec.canceled = true;
4257 mIntentSenderRecords.remove(key);
4258 }
4259 if (noCreate) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004260 return rec;
4261 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07004262 rec = new PendingIntentRecord(this, key, callingUid);
4263 mIntentSenderRecords.put(key, rec.ref);
4264 if (type == INTENT_SENDER_ACTIVITY_RESULT) {
4265 if (activity.pendingResults == null) {
4266 activity.pendingResults
4267 = new HashSet<WeakReference<PendingIntentRecord>>();
4268 }
4269 activity.pendingResults.add(rec.ref);
4270 }
4271 return rec;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004272 }
4273
4274 public void cancelIntentSender(IIntentSender sender) {
4275 if (!(sender instanceof PendingIntentRecord)) {
4276 return;
4277 }
4278 synchronized(this) {
4279 PendingIntentRecord rec = (PendingIntentRecord)sender;
4280 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004281 int uid = AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004282 .getPackageUid(rec.key.packageName);
4283 if (uid != Binder.getCallingUid()) {
4284 String msg = "Permission Denial: cancelIntentSender() from pid="
4285 + Binder.getCallingPid()
4286 + ", uid=" + Binder.getCallingUid()
4287 + " is not allowed to cancel packges "
4288 + rec.key.packageName;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004289 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004290 throw new SecurityException(msg);
4291 }
4292 } catch (RemoteException e) {
4293 throw new SecurityException(e);
4294 }
4295 cancelIntentSenderLocked(rec, true);
4296 }
4297 }
4298
4299 void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
4300 rec.canceled = true;
4301 mIntentSenderRecords.remove(rec.key);
4302 if (cleanActivity && rec.key.activity != null) {
4303 rec.key.activity.pendingResults.remove(rec.ref);
4304 }
4305 }
4306
4307 public String getPackageForIntentSender(IIntentSender pendingResult) {
4308 if (!(pendingResult instanceof PendingIntentRecord)) {
4309 return null;
4310 }
Brad Fitzpatrickb213d102010-04-19 11:58:52 -07004311 try {
4312 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
4313 return res.key.packageName;
4314 } catch (ClassCastException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004315 }
4316 return null;
4317 }
4318
Dianne Hackborn6c418d52011-06-29 14:05:33 -07004319 public boolean isIntentSenderTargetedToPackage(IIntentSender pendingResult) {
4320 if (!(pendingResult instanceof PendingIntentRecord)) {
4321 return false;
4322 }
4323 try {
4324 PendingIntentRecord res = (PendingIntentRecord)pendingResult;
4325 if (res.key.allIntents == null) {
4326 return false;
4327 }
4328 for (int i=0; i<res.key.allIntents.length; i++) {
4329 Intent intent = res.key.allIntents[i];
4330 if (intent.getPackage() != null && intent.getComponent() != null) {
4331 return false;
4332 }
4333 }
4334 return true;
4335 } catch (ClassCastException e) {
4336 }
4337 return false;
4338 }
4339
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004340 public void setProcessLimit(int max) {
4341 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4342 "setProcessLimit()");
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004343 synchronized (this) {
Dianne Hackborn7d608422011-08-07 16:24:18 -07004344 mProcessLimit = max < 0 ? ProcessList.MAX_HIDDEN_APPS : max;
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004345 mProcessLimitOverride = max;
4346 }
4347 trimApplications();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004348 }
4349
4350 public int getProcessLimit() {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07004351 synchronized (this) {
4352 return mProcessLimitOverride;
4353 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004354 }
4355
4356 void foregroundTokenDied(ForegroundToken token) {
4357 synchronized (ActivityManagerService.this) {
4358 synchronized (mPidsSelfLocked) {
4359 ForegroundToken cur
4360 = mForegroundProcesses.get(token.pid);
4361 if (cur != token) {
4362 return;
4363 }
4364 mForegroundProcesses.remove(token.pid);
4365 ProcessRecord pr = mPidsSelfLocked.get(token.pid);
4366 if (pr == null) {
4367 return;
4368 }
4369 pr.forcingToForeground = null;
4370 pr.foregroundServices = false;
4371 }
4372 updateOomAdjLocked();
4373 }
4374 }
4375
4376 public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
4377 enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
4378 "setProcessForeground()");
4379 synchronized(this) {
4380 boolean changed = false;
4381
4382 synchronized (mPidsSelfLocked) {
4383 ProcessRecord pr = mPidsSelfLocked.get(pid);
4384 if (pr == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004385 Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004386 return;
4387 }
4388 ForegroundToken oldToken = mForegroundProcesses.get(pid);
4389 if (oldToken != null) {
4390 oldToken.token.unlinkToDeath(oldToken, 0);
4391 mForegroundProcesses.remove(pid);
4392 pr.forcingToForeground = null;
4393 changed = true;
4394 }
4395 if (isForeground && token != null) {
4396 ForegroundToken newToken = new ForegroundToken() {
4397 public void binderDied() {
4398 foregroundTokenDied(this);
4399 }
4400 };
4401 newToken.pid = pid;
4402 newToken.token = token;
4403 try {
4404 token.linkToDeath(newToken, 0);
4405 mForegroundProcesses.put(pid, newToken);
4406 pr.forcingToForeground = token;
4407 changed = true;
4408 } catch (RemoteException e) {
4409 // If the process died while doing this, we will later
4410 // do the cleanup with the process death link.
4411 }
4412 }
4413 }
4414
4415 if (changed) {
4416 updateOomAdjLocked();
4417 }
4418 }
4419 }
4420
4421 // =========================================================
4422 // PERMISSIONS
4423 // =========================================================
4424
4425 static class PermissionController extends IPermissionController.Stub {
4426 ActivityManagerService mActivityManagerService;
4427 PermissionController(ActivityManagerService activityManagerService) {
4428 mActivityManagerService = activityManagerService;
4429 }
4430
4431 public boolean checkPermission(String permission, int pid, int uid) {
4432 return mActivityManagerService.checkPermission(permission, pid,
4433 uid) == PackageManager.PERMISSION_GRANTED;
4434 }
4435 }
4436
4437 /**
4438 * This can be called with or without the global lock held.
4439 */
4440 int checkComponentPermission(String permission, int pid, int uid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004441 int owningUid, boolean exported) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004442 // We might be performing an operation on behalf of an indirect binder
4443 // invocation, e.g. via {@link #openContentUri}. Check and adjust the
4444 // client identity accordingly before proceeding.
4445 Identity tlsIdentity = sCallerIdentity.get();
4446 if (tlsIdentity != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004447 Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004448 + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
4449 uid = tlsIdentity.uid;
4450 pid = tlsIdentity.pid;
4451 }
4452
4453 // Root, system server and our own process get to do everything.
Jeff Brown10e89712011-07-08 18:52:57 -07004454 if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004455 return PackageManager.PERMISSION_GRANTED;
4456 }
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004457 // If there is a uid that owns whatever is being accessed, it has
4458 // blanket access to it regardless of the permissions it requires.
4459 if (owningUid >= 0 && uid == owningUid) {
4460 return PackageManager.PERMISSION_GRANTED;
4461 }
4462 // If the target is not exported, then nobody else can get to it.
4463 if (!exported) {
4464 Slog.w(TAG, "Permission denied: checkComponentPermission() owningUid=" + owningUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004465 return PackageManager.PERMISSION_DENIED;
4466 }
4467 if (permission == null) {
4468 return PackageManager.PERMISSION_GRANTED;
4469 }
4470 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004471 return AppGlobals.getPackageManager()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004472 .checkUidPermission(permission, uid);
4473 } catch (RemoteException e) {
4474 // Should never happen, but if it does... deny!
Joe Onorato8a9b2202010-02-26 18:56:32 -08004475 Slog.e(TAG, "PackageManager is dead?!?", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004476 }
4477 return PackageManager.PERMISSION_DENIED;
4478 }
4479
4480 /**
4481 * As the only public entry point for permissions checking, this method
4482 * can enforce the semantic that requesting a check on a null global
4483 * permission is automatically denied. (Internally a null permission
4484 * string is used when calling {@link #checkComponentPermission} in cases
4485 * when only uid-based security is needed.)
4486 *
4487 * This can be called with or without the global lock held.
4488 */
4489 public int checkPermission(String permission, int pid, int uid) {
4490 if (permission == null) {
4491 return PackageManager.PERMISSION_DENIED;
4492 }
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08004493 return checkComponentPermission(permission, pid, uid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004494 }
4495
4496 /**
4497 * Binder IPC calls go through the public entry point.
4498 * This can be called with or without the global lock held.
4499 */
4500 int checkCallingPermission(String permission) {
4501 return checkPermission(permission,
4502 Binder.getCallingPid(),
4503 Binder.getCallingUid());
4504 }
4505
4506 /**
4507 * This can be called with or without the global lock held.
4508 */
4509 void enforceCallingPermission(String permission, String func) {
4510 if (checkCallingPermission(permission)
4511 == PackageManager.PERMISSION_GRANTED) {
4512 return;
4513 }
4514
4515 String msg = "Permission Denial: " + func + " from pid="
4516 + Binder.getCallingPid()
4517 + ", uid=" + Binder.getCallingUid()
4518 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08004519 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004520 throw new SecurityException(msg);
4521 }
4522
4523 private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
Dianne Hackborn48058e82010-09-27 16:53:23 -07004524 ProviderInfo pi, Uri uri, int uid, int modeFlags) {
4525 boolean readPerm = (modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0;
4526 boolean writePerm = (modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0;
4527 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4528 "checkHoldingPermissionsLocked: uri=" + uri + " uid=" + uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004529 try {
Dianne Hackborn48058e82010-09-27 16:53:23 -07004530 // Is the component private from the target uid?
4531 final boolean prv = !pi.exported && pi.applicationInfo.uid != uid;
4532
4533 // Acceptable if the there is no read permission needed from the
4534 // target or the target is holding the read permission.
4535 if (!readPerm) {
4536 if ((!prv && pi.readPermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004537 (pm.checkUidPermission(pi.readPermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004538 == PackageManager.PERMISSION_GRANTED)) {
4539 readPerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004540 }
4541 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004542
4543 // Acceptable if the there is no write permission needed from the
4544 // target or the target is holding the read permission.
4545 if (!writePerm) {
4546 if (!prv && (pi.writePermission == null) ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004547 (pm.checkUidPermission(pi.writePermission, uid)
Dianne Hackborn48058e82010-09-27 16:53:23 -07004548 == PackageManager.PERMISSION_GRANTED)) {
4549 writePerm = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004550 }
4551 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004552
4553 // Acceptable if there is a path permission matching the URI that
4554 // the target holds the permission on.
4555 PathPermission[] pps = pi.pathPermissions;
4556 if (pps != null && (!readPerm || !writePerm)) {
4557 final String path = uri.getPath();
4558 int i = pps.length;
4559 while (i > 0 && (!readPerm || !writePerm)) {
4560 i--;
4561 PathPermission pp = pps[i];
4562 if (!readPerm) {
4563 final String pprperm = pp.getReadPermission();
4564 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking read perm for "
4565 + pprperm + " for " + pp.getPath()
4566 + ": match=" + pp.match(path)
4567 + " check=" + pm.checkUidPermission(pprperm, uid));
4568 if (pprperm != null && pp.match(path) &&
4569 (pm.checkUidPermission(pprperm, uid)
4570 == PackageManager.PERMISSION_GRANTED)) {
4571 readPerm = true;
4572 }
4573 }
4574 if (!writePerm) {
4575 final String ppwperm = pp.getWritePermission();
4576 if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking write perm "
4577 + ppwperm + " for " + pp.getPath()
4578 + ": match=" + pp.match(path)
4579 + " check=" + pm.checkUidPermission(ppwperm, uid));
4580 if (ppwperm != null && pp.match(path) &&
4581 (pm.checkUidPermission(ppwperm, uid)
4582 == PackageManager.PERMISSION_GRANTED)) {
4583 writePerm = true;
4584 }
4585 }
4586 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004587 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004588 } catch (RemoteException e) {
4589 return false;
4590 }
Dianne Hackborn48058e82010-09-27 16:53:23 -07004591
4592 return readPerm && writePerm;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004593 }
4594
4595 private final boolean checkUriPermissionLocked(Uri uri, int uid,
4596 int modeFlags) {
4597 // Root gets to do everything.
Jeff Brown10e89712011-07-08 18:52:57 -07004598 if (uid == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004599 return true;
4600 }
4601 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
4602 if (perms == null) return false;
4603 UriPermission perm = perms.get(uri);
4604 if (perm == null) return false;
4605 return (modeFlags&perm.modeFlags) == modeFlags;
4606 }
4607
4608 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
4609 // Another redirected-binder-call permissions check as in
4610 // {@link checkComponentPermission}.
4611 Identity tlsIdentity = sCallerIdentity.get();
4612 if (tlsIdentity != null) {
4613 uid = tlsIdentity.uid;
4614 pid = tlsIdentity.pid;
4615 }
4616
4617 // Our own process gets to do everything.
4618 if (pid == MY_PID) {
4619 return PackageManager.PERMISSION_GRANTED;
4620 }
4621 synchronized(this) {
4622 return checkUriPermissionLocked(uri, uid, modeFlags)
4623 ? PackageManager.PERMISSION_GRANTED
4624 : PackageManager.PERMISSION_DENIED;
4625 }
4626 }
4627
Dianne Hackborn39792d22010-08-19 18:01:52 -07004628 /**
4629 * Check if the targetPkg can be granted permission to access uri by
4630 * the callingUid using the given modeFlags. Throws a security exception
4631 * if callingUid is not allowed to do this. Returns the uid of the target
4632 * if the URI permission grant should be performed; returns -1 if it is not
4633 * needed (for example targetPkg already has permission to access the URI).
4634 */
4635 int checkGrantUriPermissionLocked(int callingUid, String targetPkg,
4636 Uri uri, int modeFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004637 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4638 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4639 if (modeFlags == 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004640 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004641 }
4642
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004643 if (targetPkg != null) {
4644 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4645 "Checking grant " + targetPkg + " permission to " + uri);
4646 }
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004647
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004648 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004649
4650 // If this is not a content: uri, we can't do anything with it.
4651 if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004652 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004653 "Can't grant URI permission for non-content URI: " + uri);
Dianne Hackborn39792d22010-08-19 18:01:52 -07004654 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004655 }
4656
4657 String name = uri.getAuthority();
4658 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004659 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004660 if (cpr != null) {
4661 pi = cpr.info;
4662 } else {
4663 try {
4664 pi = pm.resolveContentProvider(name,
4665 PackageManager.GET_URI_PERMISSION_PATTERNS);
4666 } catch (RemoteException ex) {
4667 }
4668 }
4669 if (pi == null) {
Dianne Hackborn98cfebc2011-10-18 13:17:33 -07004670 Slog.w(TAG, "No content provider found for permission check: " + uri.toSafeString());
Dianne Hackborn39792d22010-08-19 18:01:52 -07004671 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004672 }
4673
4674 int targetUid;
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004675 if (targetPkg != null) {
4676 try {
4677 targetUid = pm.getPackageUid(targetPkg);
4678 if (targetUid < 0) {
4679 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4680 "Can't grant URI permission no uid for: " + targetPkg);
4681 return -1;
4682 }
4683 } catch (RemoteException ex) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004684 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004685 }
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004686 } else {
4687 targetUid = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004688 }
4689
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004690 if (targetUid >= 0) {
4691 // First... does the target actually need this permission?
4692 if (checkHoldingPermissionsLocked(pm, pi, uri, targetUid, modeFlags)) {
4693 // No need to grant the target this permission.
4694 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
4695 "Target " + targetPkg + " already has full permission to " + uri);
4696 return -1;
4697 }
4698 } else {
4699 // First... there is no target package, so can anyone access it?
4700 boolean allowed = pi.exported;
4701 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4702 if (pi.readPermission != null) {
4703 allowed = false;
4704 }
4705 }
4706 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4707 if (pi.writePermission != null) {
4708 allowed = false;
4709 }
4710 }
4711 if (allowed) {
4712 return -1;
4713 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004714 }
4715
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004716 // Second... is the provider allowing granting of URI permissions?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004717 if (!pi.grantUriPermissions) {
4718 throw new SecurityException("Provider " + pi.packageName
4719 + "/" + pi.name
4720 + " does not allow granting of Uri permissions (uri "
4721 + uri + ")");
4722 }
4723 if (pi.uriPermissionPatterns != null) {
4724 final int N = pi.uriPermissionPatterns.length;
4725 boolean allowed = false;
4726 for (int i=0; i<N; i++) {
4727 if (pi.uriPermissionPatterns[i] != null
4728 && pi.uriPermissionPatterns[i].match(uri.getPath())) {
4729 allowed = true;
4730 break;
4731 }
4732 }
4733 if (!allowed) {
4734 throw new SecurityException("Provider " + pi.packageName
4735 + "/" + pi.name
4736 + " does not allow granting of permission to path of Uri "
4737 + uri);
4738 }
4739 }
4740
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004741 // Third... does the caller itself have permission to access
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004742 // this uri?
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004743 if (callingUid != Process.myUid()) {
4744 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
4745 if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4746 throw new SecurityException("Uid " + callingUid
4747 + " does not have permission to uri " + uri);
4748 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004749 }
4750 }
4751
Dianne Hackborn39792d22010-08-19 18:01:52 -07004752 return targetUid;
4753 }
4754
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004755 public int checkGrantUriPermission(int callingUid, String targetPkg,
4756 Uri uri, int modeFlags) {
4757 synchronized(this) {
4758 return checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4759 }
4760 }
4761
Dianne Hackborn39792d22010-08-19 18:01:52 -07004762 void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg,
4763 Uri uri, int modeFlags, UriPermissionOwner owner) {
4764 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4765 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4766 if (modeFlags == 0) {
4767 return;
4768 }
4769
4770 // So here we are: the caller has the assumed permission
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004771 // to the uri, and the target doesn't. Let's now give this to
4772 // the target.
4773
Joe Onorato8a9b2202010-02-26 18:56:32 -08004774 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004775 "Granting " + targetPkg + "/" + targetUid + " permission to " + uri);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004776
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004777 HashMap<Uri, UriPermission> targetUris
4778 = mGrantedUriPermissions.get(targetUid);
4779 if (targetUris == null) {
4780 targetUris = new HashMap<Uri, UriPermission>();
4781 mGrantedUriPermissions.put(targetUid, targetUris);
4782 }
4783
4784 UriPermission perm = targetUris.get(uri);
4785 if (perm == null) {
4786 perm = new UriPermission(targetUid, uri);
4787 targetUris.put(uri, perm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004788 }
Dianne Hackbornb424b632010-08-18 15:59:05 -07004789
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004790 perm.modeFlags |= modeFlags;
Dianne Hackborn39792d22010-08-19 18:01:52 -07004791 if (owner == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004792 perm.globalModeFlags |= modeFlags;
Vairavan Srinivasan91c12c22011-01-21 18:26:06 -08004793 } else {
4794 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
4795 perm.readOwners.add(owner);
4796 owner.addReadPermission(perm);
4797 }
4798 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
4799 perm.writeOwners.add(owner);
4800 owner.addWritePermission(perm);
4801 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004802 }
4803 }
4804
Dianne Hackborn39792d22010-08-19 18:01:52 -07004805 void grantUriPermissionLocked(int callingUid,
4806 String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) {
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004807 if (targetPkg == null) {
4808 throw new NullPointerException("targetPkg");
4809 }
4810
Dianne Hackborn39792d22010-08-19 18:01:52 -07004811 int targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
4812 if (targetUid < 0) {
4813 return;
4814 }
4815
4816 grantUriPermissionUncheckedLocked(targetUid, targetPkg, uri, modeFlags, owner);
4817 }
4818
4819 /**
4820 * Like checkGrantUriPermissionLocked, but takes an Intent.
4821 */
4822 int checkGrantUriPermissionFromIntentLocked(int callingUid,
4823 String targetPkg, Intent intent) {
Dianne Hackbornb424b632010-08-18 15:59:05 -07004824 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn39792d22010-08-19 18:01:52 -07004825 "Checking URI perm to " + (intent != null ? intent.getData() : null)
Dianne Hackbornb424b632010-08-18 15:59:05 -07004826 + " from " + intent + "; flags=0x"
4827 + Integer.toHexString(intent != null ? intent.getFlags() : 0));
4828
Dianne Hackborn90f4aaf2010-09-27 14:58:44 -07004829 if (targetPkg == null) {
4830 throw new NullPointerException("targetPkg");
4831 }
4832
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004833 if (intent == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004834 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004835 }
4836 Uri data = intent.getData();
4837 if (data == null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -07004838 return -1;
4839 }
4840 return checkGrantUriPermissionLocked(callingUid, targetPkg, data,
4841 intent.getFlags());
4842 }
4843
4844 /**
4845 * Like grantUriPermissionUncheckedLocked, but takes an Intent.
4846 */
4847 void grantUriPermissionUncheckedFromIntentLocked(int targetUid,
4848 String targetPkg, Intent intent, UriPermissionOwner owner) {
4849 grantUriPermissionUncheckedLocked(targetUid, targetPkg, intent.getData(),
4850 intent.getFlags(), owner);
4851 }
4852
4853 void grantUriPermissionFromIntentLocked(int callingUid,
4854 String targetPkg, Intent intent, UriPermissionOwner owner) {
4855 int targetUid = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg, intent);
4856 if (targetUid < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004857 return;
4858 }
Dianne Hackborn39792d22010-08-19 18:01:52 -07004859
4860 grantUriPermissionUncheckedFromIntentLocked(targetUid, targetPkg, intent, owner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004861 }
4862
4863 public void grantUriPermission(IApplicationThread caller, String targetPkg,
4864 Uri uri, int modeFlags) {
4865 synchronized(this) {
4866 final ProcessRecord r = getRecordForAppLocked(caller);
4867 if (r == null) {
4868 throw new SecurityException("Unable to find app for caller "
4869 + caller
4870 + " when granting permission to uri " + uri);
4871 }
4872 if (targetPkg == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004873 throw new IllegalArgumentException("null target");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004874 }
4875 if (uri == null) {
Dianne Hackborn7e269642010-08-25 19:50:20 -07004876 throw new IllegalArgumentException("null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004877 }
4878
4879 grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags,
4880 null);
4881 }
4882 }
4883
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07004884 void removeUriPermissionIfNeededLocked(UriPermission perm) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004885 if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
4886 |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
4887 HashMap<Uri, UriPermission> perms
4888 = mGrantedUriPermissions.get(perm.uid);
4889 if (perms != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004890 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004891 "Removing " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004892 perms.remove(perm.uri);
4893 if (perms.size() == 0) {
4894 mGrantedUriPermissions.remove(perm.uid);
4895 }
4896 }
4897 }
4898 }
4899
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004900 private void revokeUriPermissionLocked(int callingUid, Uri uri,
4901 int modeFlags) {
4902 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
4903 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
4904 if (modeFlags == 0) {
4905 return;
4906 }
4907
Joe Onorato8a9b2202010-02-26 18:56:32 -08004908 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004909 "Revoking all granted permissions to " + uri);
4910
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07004911 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004912
4913 final String authority = uri.getAuthority();
4914 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07004915 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004916 if (cpr != null) {
4917 pi = cpr.info;
4918 } else {
4919 try {
4920 pi = pm.resolveContentProvider(authority,
4921 PackageManager.GET_URI_PERMISSION_PATTERNS);
4922 } catch (RemoteException ex) {
4923 }
4924 }
4925 if (pi == null) {
Dianne Hackborn98cfebc2011-10-18 13:17:33 -07004926 Slog.w(TAG, "No content provider found for permission revoke: " + uri.toSafeString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004927 return;
4928 }
4929
4930 // Does the caller have this permission on the URI?
Dianne Hackborn48058e82010-09-27 16:53:23 -07004931 if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004932 // Right now, if you are not the original owner of the permission,
4933 // you are not allowed to revoke it.
4934 //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
4935 throw new SecurityException("Uid " + callingUid
4936 + " does not have permission to uri " + uri);
4937 //}
4938 }
4939
4940 // Go through all of the permissions and remove any that match.
4941 final List<String> SEGMENTS = uri.getPathSegments();
4942 if (SEGMENTS != null) {
4943 final int NS = SEGMENTS.size();
4944 int N = mGrantedUriPermissions.size();
4945 for (int i=0; i<N; i++) {
4946 HashMap<Uri, UriPermission> perms
4947 = mGrantedUriPermissions.valueAt(i);
4948 Iterator<UriPermission> it = perms.values().iterator();
4949 toploop:
4950 while (it.hasNext()) {
4951 UriPermission perm = it.next();
4952 Uri targetUri = perm.uri;
4953 if (!authority.equals(targetUri.getAuthority())) {
4954 continue;
4955 }
4956 List<String> targetSegments = targetUri.getPathSegments();
4957 if (targetSegments == null) {
4958 continue;
4959 }
4960 if (targetSegments.size() < NS) {
4961 continue;
4962 }
4963 for (int j=0; j<NS; j++) {
4964 if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
4965 continue toploop;
4966 }
4967 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004968 if (DEBUG_URI_PERMISSION) Slog.v(TAG,
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08004969 "Revoking " + perm.uid + " permission to " + perm.uri);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004970 perm.clearModes(modeFlags);
4971 if (perm.modeFlags == 0) {
4972 it.remove();
4973 }
4974 }
4975 if (perms.size() == 0) {
4976 mGrantedUriPermissions.remove(
4977 mGrantedUriPermissions.keyAt(i));
4978 N--;
4979 i--;
4980 }
4981 }
4982 }
4983 }
4984
4985 public void revokeUriPermission(IApplicationThread caller, Uri uri,
4986 int modeFlags) {
4987 synchronized(this) {
4988 final ProcessRecord r = getRecordForAppLocked(caller);
4989 if (r == null) {
4990 throw new SecurityException("Unable to find app for caller "
4991 + caller
4992 + " when revoking permission to uri " + uri);
4993 }
4994 if (uri == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004995 Slog.w(TAG, "revokeUriPermission: null uri");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004996 return;
4997 }
4998
4999 modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
5000 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
5001 if (modeFlags == 0) {
5002 return;
5003 }
5004
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005005 final IPackageManager pm = AppGlobals.getPackageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005006
5007 final String authority = uri.getAuthority();
5008 ProviderInfo pi = null;
Dianne Hackborn860755f2010-06-03 18:47:52 -07005009 ContentProviderRecord cpr = mProvidersByName.get(authority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005010 if (cpr != null) {
5011 pi = cpr.info;
5012 } else {
5013 try {
5014 pi = pm.resolveContentProvider(authority,
5015 PackageManager.GET_URI_PERMISSION_PATTERNS);
5016 } catch (RemoteException ex) {
5017 }
5018 }
5019 if (pi == null) {
Dianne Hackborn98cfebc2011-10-18 13:17:33 -07005020 Slog.w(TAG, "No content provider found for permission revoke: "
5021 + uri.toSafeString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005022 return;
5023 }
5024
5025 revokeUriPermissionLocked(r.info.uid, uri, modeFlags);
5026 }
5027 }
5028
Dianne Hackborn7e269642010-08-25 19:50:20 -07005029 @Override
5030 public IBinder newUriPermissionOwner(String name) {
5031 synchronized(this) {
5032 UriPermissionOwner owner = new UriPermissionOwner(this, name);
5033 return owner.getExternalTokenLocked();
5034 }
5035 }
5036
5037 @Override
5038 public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg,
5039 Uri uri, int modeFlags) {
5040 synchronized(this) {
5041 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
5042 if (owner == null) {
5043 throw new IllegalArgumentException("Unknown owner: " + token);
5044 }
5045 if (fromUid != Binder.getCallingUid()) {
5046 if (Binder.getCallingUid() != Process.myUid()) {
5047 // Only system code can grant URI permissions on behalf
5048 // of other users.
5049 throw new SecurityException("nice try");
5050 }
5051 }
5052 if (targetPkg == null) {
5053 throw new IllegalArgumentException("null target");
5054 }
5055 if (uri == null) {
5056 throw new IllegalArgumentException("null uri");
5057 }
5058
5059 grantUriPermissionLocked(fromUid, targetPkg, uri, modeFlags, owner);
5060 }
5061 }
5062
5063 @Override
5064 public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode) {
5065 synchronized(this) {
5066 UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
5067 if (owner == null) {
5068 throw new IllegalArgumentException("Unknown owner: " + token);
5069 }
5070
5071 if (uri == null) {
5072 owner.removeUriPermissionsLocked(mode);
5073 } else {
5074 owner.removeUriPermissionLocked(uri, mode);
5075 }
5076 }
5077 }
5078
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005079 public void showWaitingForDebugger(IApplicationThread who, boolean waiting) {
5080 synchronized (this) {
5081 ProcessRecord app =
5082 who != null ? getRecordForAppLocked(who) : null;
5083 if (app == null) return;
5084
5085 Message msg = Message.obtain();
5086 msg.what = WAIT_FOR_DEBUGGER_MSG;
5087 msg.obj = app;
5088 msg.arg1 = waiting ? 1 : 0;
5089 mHandler.sendMessage(msg);
5090 }
5091 }
5092
5093 public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
Dianne Hackborn7d608422011-08-07 16:24:18 -07005094 final long homeAppMem = mProcessList.getMemLevel(ProcessList.HOME_APP_ADJ);
5095 final long hiddenAppMem = mProcessList.getMemLevel(ProcessList.HIDDEN_APP_MIN_ADJ);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005096 outInfo.availMem = Process.getFreeMemory();
Dianne Hackborn7d608422011-08-07 16:24:18 -07005097 outInfo.threshold = homeAppMem;
5098 outInfo.lowMemory = outInfo.availMem < (homeAppMem + ((hiddenAppMem-homeAppMem)/2));
5099 outInfo.hiddenAppThreshold = hiddenAppMem;
5100 outInfo.secondaryServerThreshold = mProcessList.getMemLevel(
Dianne Hackborne02c88a2011-10-28 13:58:15 -07005101 ProcessList.SERVICE_ADJ);
Dianne Hackborn7d608422011-08-07 16:24:18 -07005102 outInfo.visibleAppThreshold = mProcessList.getMemLevel(
5103 ProcessList.VISIBLE_APP_ADJ);
5104 outInfo.foregroundAppThreshold = mProcessList.getMemLevel(
5105 ProcessList.FOREGROUND_APP_ADJ);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005106 }
5107
5108 // =========================================================
5109 // TASK MANAGEMENT
5110 // =========================================================
5111
5112 public List getTasks(int maxNum, int flags,
5113 IThumbnailReceiver receiver) {
5114 ArrayList list = new ArrayList();
5115
5116 PendingThumbnailsRecord pending = null;
5117 IApplicationThread topThumbnail = null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005118 ActivityRecord topRecord = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005119
5120 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005121 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005122 TAG, "getTasks: max=" + maxNum + ", flags=" + flags
5123 + ", receiver=" + receiver);
5124
5125 if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
5126 != PackageManager.PERMISSION_GRANTED) {
5127 if (receiver != null) {
5128 // If the caller wants to wait for pending thumbnails,
5129 // it ain't gonna get them.
5130 try {
5131 receiver.finished();
5132 } catch (RemoteException ex) {
5133 }
5134 }
5135 String msg = "Permission Denial: getTasks() from pid="
5136 + Binder.getCallingPid()
5137 + ", uid=" + Binder.getCallingUid()
5138 + " requires " + android.Manifest.permission.GET_TASKS;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005139 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005140 throw new SecurityException(msg);
5141 }
5142
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005143 int pos = mMainStack.mHistory.size()-1;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005144 ActivityRecord next =
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005145 pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005146 ActivityRecord top = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005147 TaskRecord curTask = null;
5148 int numActivities = 0;
5149 int numRunning = 0;
5150 while (pos >= 0 && maxNum > 0) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005151 final ActivityRecord r = next;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005152 pos--;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005153 next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005154
5155 // Initialize state for next task if needed.
5156 if (top == null ||
5157 (top.state == ActivityState.INITIALIZING
5158 && top.task == r.task)) {
5159 top = r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005160 curTask = r.task;
5161 numActivities = numRunning = 0;
5162 }
5163
5164 // Add 'r' into the current task.
5165 numActivities++;
5166 if (r.app != null && r.app.thread != null) {
5167 numRunning++;
5168 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005169
Joe Onorato8a9b2202010-02-26 18:56:32 -08005170 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005171 TAG, r.intent.getComponent().flattenToShortString()
5172 + ": task=" + r.task);
5173
5174 // If the next one is a different task, generate a new
5175 // TaskInfo entry for what we have.
5176 if (next == null || next.task != curTask) {
5177 ActivityManager.RunningTaskInfo ci
5178 = new ActivityManager.RunningTaskInfo();
5179 ci.id = curTask.taskId;
5180 ci.baseActivity = r.intent.getComponent();
5181 ci.topActivity = top.intent.getComponent();
Dianne Hackbornf26fd992011-04-08 18:14:09 -07005182 if (top.thumbHolder != null) {
5183 ci.description = top.thumbHolder.lastDescription;
5184 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005185 ci.numActivities = numActivities;
5186 ci.numRunning = numRunning;
5187 //System.out.println(
5188 // "#" + maxNum + ": " + " descr=" + ci.description);
5189 if (ci.thumbnail == null && receiver != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005190 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005191 TAG, "State=" + top.state + "Idle=" + top.idle
5192 + " app=" + top.app
5193 + " thr=" + (top.app != null ? top.app.thread : null));
5194 if (top.state == ActivityState.RESUMED
5195 || top.state == ActivityState.PAUSING) {
5196 if (top.idle && top.app != null
5197 && top.app.thread != null) {
5198 topRecord = top;
5199 topThumbnail = top.app.thread;
5200 } else {
5201 top.thumbnailNeeded = true;
5202 }
5203 }
5204 if (pending == null) {
5205 pending = new PendingThumbnailsRecord(receiver);
5206 }
5207 pending.pendingRecords.add(top);
5208 }
5209 list.add(ci);
5210 maxNum--;
5211 top = null;
5212 }
5213 }
5214
5215 if (pending != null) {
5216 mPendingThumbnails.add(pending);
5217 }
5218 }
5219
Joe Onorato8a9b2202010-02-26 18:56:32 -08005220 if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005221
5222 if (topThumbnail != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005223 if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005224 try {
Dianne Hackbornbe707852011-11-11 14:32:10 -08005225 topThumbnail.requestThumbnail(topRecord.appToken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005226 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005227 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
Dianne Hackbornbe707852011-11-11 14:32:10 -08005228 sendPendingThumbnail(null, topRecord.appToken, null, null, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005229 }
5230 }
5231
5232 if (pending == null && receiver != null) {
5233 // In this case all thumbnails were available and the client
5234 // is being asked to be told when the remaining ones come in...
5235 // which is unusually, since the top-most currently running
5236 // activity should never have a canned thumbnail! Oh well.
5237 try {
5238 receiver.finished();
5239 } catch (RemoteException ex) {
5240 }
5241 }
5242
5243 return list;
5244 }
5245
5246 public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
5247 int flags) {
5248 synchronized (this) {
5249 enforceCallingPermission(android.Manifest.permission.GET_TASKS,
5250 "getRecentTasks()");
5251
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005252 IPackageManager pm = AppGlobals.getPackageManager();
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07005253
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005254 final int N = mRecentTasks.size();
5255 ArrayList<ActivityManager.RecentTaskInfo> res
5256 = new ArrayList<ActivityManager.RecentTaskInfo>(
5257 maxNum < N ? maxNum : N);
5258 for (int i=0; i<N && maxNum > 0; i++) {
5259 TaskRecord tr = mRecentTasks.get(i);
Dianne Hackborn905577f2011-09-07 18:31:28 -07005260 // Return the entry if desired by the caller. We always return
5261 // the first entry, because callers always expect this to be the
5262 // forground app. We may filter others if the caller has
5263 // not supplied RECENT_WITH_EXCLUDED and there is some reason
5264 // we should exclude the entry.
5265 if (i == 0
5266 || ((flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005267 || (tr.intent == null)
5268 || ((tr.intent.getFlags()
5269 &Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
5270 ActivityManager.RecentTaskInfo rti
5271 = new ActivityManager.RecentTaskInfo();
5272 rti.id = tr.numActivities > 0 ? tr.taskId : -1;
Dianne Hackbornd94df452011-02-16 18:53:31 -08005273 rti.persistentId = tr.taskId;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005274 rti.baseIntent = new Intent(
5275 tr.intent != null ? tr.intent : tr.affinityIntent);
5276 rti.origActivity = tr.origActivity;
Dianne Hackbornd2835932010-12-13 16:28:46 -08005277 rti.description = tr.lastDescription;
5278
Dianne Hackborn53d9264d2010-04-13 12:49:14 -07005279 if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
5280 // Check whether this activity is currently available.
5281 try {
5282 if (rti.origActivity != null) {
5283 if (pm.getActivityInfo(rti.origActivity, 0) == null) {
5284 continue;
5285 }
5286 } else if (rti.baseIntent != null) {
5287 if (pm.queryIntentActivities(rti.baseIntent,
5288 null, 0) == null) {
5289 continue;
5290 }
5291 }
5292 } catch (RemoteException e) {
5293 // Will never happen.
5294 }
5295 }
5296
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005297 res.add(rti);
5298 maxNum--;
5299 }
5300 }
5301 return res;
5302 }
5303 }
5304
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005305 private TaskRecord taskForIdLocked(int id) {
5306 final int N = mRecentTasks.size();
5307 for (int i=0; i<N; i++) {
5308 TaskRecord tr = mRecentTasks.get(i);
5309 if (tr.taskId == id) {
5310 return tr;
Dianne Hackbornd94df452011-02-16 18:53:31 -08005311 }
5312 }
5313 return null;
5314 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005315
5316 public ActivityManager.TaskThumbnails getTaskThumbnails(int id) {
5317 synchronized (this) {
5318 enforceCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER,
5319 "getTaskThumbnails()");
5320 TaskRecord tr = taskForIdLocked(id);
5321 if (tr != null) {
5322 return mMainStack.getTaskThumbnailsLocked(tr);
5323 }
5324 }
5325 return null;
5326 }
5327
5328 public boolean removeSubTask(int taskId, int subTaskIndex) {
5329 synchronized (this) {
5330 enforceCallingPermission(android.Manifest.permission.REMOVE_TASKS,
5331 "removeSubTask()");
5332 long ident = Binder.clearCallingIdentity();
5333 try {
5334 return mMainStack.removeTaskActivitiesLocked(taskId, subTaskIndex) != null;
5335 } finally {
5336 Binder.restoreCallingIdentity(ident);
5337 }
5338 }
5339 }
5340
Dianne Hackborn8894cc52011-07-01 16:28:17 -07005341 private void cleanUpRemovedTaskLocked(ActivityRecord root, boolean killProcesses) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005342 TaskRecord tr = root.task;
5343 Intent baseIntent = new Intent(
5344 tr.intent != null ? tr.intent : tr.affinityIntent);
5345 ComponentName component = baseIntent.getComponent();
5346 if (component == null) {
5347 Slog.w(TAG, "Now component for base intent of task: " + tr);
5348 return;
5349 }
5350
5351 // Find any running services associated with this app.
5352 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
5353 for (ServiceRecord sr : mServices.values()) {
5354 if (sr.packageName.equals(component.getPackageName())) {
5355 services.add(sr);
5356 }
5357 }
5358
5359 // Take care of any running services associated with the app.
5360 for (int i=0; i<services.size(); i++) {
5361 ServiceRecord sr = services.get(i);
5362 if (sr.startRequested) {
5363 if ((sr.serviceInfo.flags&ServiceInfo.FLAG_STOP_WITH_TASK) != 0) {
Dianne Hackborn8894cc52011-07-01 16:28:17 -07005364 Slog.i(TAG, "Stopping service " + sr.shortName + ": remove task");
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005365 stopServiceLocked(sr);
5366 } else {
5367 sr.pendingStarts.add(new ServiceRecord.StartItem(sr, true,
5368 sr.makeNextStartId(), baseIntent, -1));
5369 if (sr.app != null && sr.app.thread != null) {
5370 sendServiceArgsLocked(sr, false);
5371 }
5372 }
5373 }
5374 }
5375
Dianne Hackborn8894cc52011-07-01 16:28:17 -07005376 if (killProcesses) {
5377 // Find any running processes associated with this app.
5378 ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
5379 SparseArray<ProcessRecord> appProcs
5380 = mProcessNames.getMap().get(component.getPackageName());
5381 if (appProcs != null) {
5382 for (int i=0; i<appProcs.size(); i++) {
5383 procs.add(appProcs.valueAt(i));
5384 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005385 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005386
Dianne Hackborn8894cc52011-07-01 16:28:17 -07005387 // Kill the running processes.
5388 for (int i=0; i<procs.size(); i++) {
5389 ProcessRecord pr = procs.get(i);
5390 if (pr.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {
5391 Slog.i(TAG, "Killing " + pr.toShortString() + ": remove task");
5392 EventLog.writeEvent(EventLogTags.AM_KILL, pr.pid,
5393 pr.processName, pr.setAdj, "remove task");
5394 Process.killProcessQuiet(pr.pid);
5395 } else {
5396 pr.waitingToKill = "remove task";
5397 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005398 }
5399 }
5400 }
5401
5402 public boolean removeTask(int taskId, int flags) {
5403 synchronized (this) {
5404 enforceCallingPermission(android.Manifest.permission.REMOVE_TASKS,
5405 "removeTask()");
5406 long ident = Binder.clearCallingIdentity();
5407 try {
5408 ActivityRecord r = mMainStack.removeTaskActivitiesLocked(taskId, -1);
5409 if (r != null) {
5410 mRecentTasks.remove(r.task);
Dianne Hackborn8894cc52011-07-01 16:28:17 -07005411 cleanUpRemovedTaskLocked(r,
5412 (flags&ActivityManager.REMOVE_TASK_KILL_PROCESS) != 0);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005413 return true;
Dianne Hackborneeb1dca2011-09-08 13:30:11 -07005414 } else {
5415 TaskRecord tr = null;
5416 int i=0;
5417 while (i < mRecentTasks.size()) {
5418 TaskRecord t = mRecentTasks.get(i);
5419 if (t.taskId == taskId) {
5420 tr = t;
5421 break;
5422 }
5423 i++;
5424 }
5425 if (tr != null) {
5426 if (tr.numActivities <= 0) {
5427 // Caller is just removing a recent task that is
5428 // not actively running. That is easy!
5429 mRecentTasks.remove(i);
5430 } else {
5431 Slog.w(TAG, "removeTask: task " + taskId
5432 + " does not have activities to remove, "
5433 + " but numActivities=" + tr.numActivities
5434 + ": " + tr);
5435 }
5436 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005437 }
5438 } finally {
5439 Binder.restoreCallingIdentity(ident);
5440 }
5441 }
5442 return false;
5443 }
Dianne Hackbornd94df452011-02-16 18:53:31 -08005444
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005445 private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
5446 int j;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005447 TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005448 TaskRecord jt = startTask;
5449
5450 // First look backwards
5451 for (j=startIndex-1; j>=0; j--) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005452 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005453 if (r.task != jt) {
5454 jt = r.task;
5455 if (affinity.equals(jt.affinity)) {
5456 return j;
5457 }
5458 }
5459 }
5460
5461 // Now look forwards
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005462 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005463 jt = startTask;
5464 for (j=startIndex+1; j<N; j++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005465 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005466 if (r.task != jt) {
5467 if (affinity.equals(jt.affinity)) {
5468 return j;
5469 }
5470 jt = r.task;
5471 }
5472 }
5473
5474 // Might it be at the top?
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005475 if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005476 return N-1;
5477 }
5478
5479 return -1;
5480 }
5481
5482 /**
Dianne Hackbornb06ea702009-07-13 13:07:51 -07005483 * TODO: Add mController hook
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005484 */
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005485 public void moveTaskToFront(int task, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005486 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5487 "moveTaskToFront()");
5488
5489 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005490 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5491 Binder.getCallingUid(), "Task to front")) {
5492 return;
5493 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005494 final long origId = Binder.clearCallingIdentity();
5495 try {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005496 TaskRecord tr = taskForIdLocked(task);
5497 if (tr != null) {
5498 if ((flags&ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
5499 mMainStack.mUserLeaving = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005500 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07005501 if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
5502 // Caller wants the home activity moved with it. To accomplish this,
5503 // we'll just move the home task to the top first.
5504 mMainStack.moveHomeToFrontLocked();
5505 }
5506 mMainStack.moveTaskToFrontLocked(tr, null);
5507 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005508 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005509 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
5510 ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005511 if (hr.task.taskId == task) {
Dianne Hackbornd94df452011-02-16 18:53:31 -08005512 if ((flags&ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
5513 mMainStack.mUserLeaving = true;
5514 }
Dianne Hackborn621e17d2010-11-22 15:59:56 -08005515 if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
5516 // Caller wants the home activity moved with it. To accomplish this,
5517 // we'll just move the home task to the top first.
5518 mMainStack.moveHomeToFrontLocked();
5519 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005520 mMainStack.moveTaskToFrontLocked(hr.task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005521 return;
5522 }
5523 }
5524 } finally {
5525 Binder.restoreCallingIdentity(origId);
5526 }
5527 }
5528 }
5529
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005530 public void moveTaskToBack(int task) {
5531 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5532 "moveTaskToBack()");
5533
5534 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005535 if (mMainStack.mResumedActivity != null
5536 && mMainStack.mResumedActivity.task.taskId == task) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005537 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5538 Binder.getCallingUid(), "Task to back")) {
5539 return;
5540 }
5541 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005542 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005543 mMainStack.moveTaskToBackLocked(task, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005544 Binder.restoreCallingIdentity(origId);
5545 }
5546 }
5547
5548 /**
5549 * Moves an activity, and all of the other activities within the same task, to the bottom
5550 * of the history stack. The activity's order within the task is unchanged.
5551 *
5552 * @param token A reference to the activity we wish to move
5553 * @param nonRoot If false then this only works if the activity is the root
5554 * of a task; if true it will work for any activity in a task.
5555 * @return Returns true if the move completed, false if not.
5556 */
5557 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
5558 synchronized(this) {
5559 final long origId = Binder.clearCallingIdentity();
5560 int taskId = getTaskForActivityLocked(token, !nonRoot);
5561 if (taskId >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005562 return mMainStack.moveTaskToBackLocked(taskId, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005563 }
5564 Binder.restoreCallingIdentity(origId);
5565 }
5566 return false;
5567 }
5568
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005569 public void moveTaskBackwards(int task) {
5570 enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
5571 "moveTaskBackwards()");
5572
5573 synchronized(this) {
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07005574 if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
5575 Binder.getCallingUid(), "Task backwards")) {
5576 return;
5577 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005578 final long origId = Binder.clearCallingIdentity();
5579 moveTaskBackwardsLocked(task);
5580 Binder.restoreCallingIdentity(origId);
5581 }
5582 }
5583
5584 private final void moveTaskBackwardsLocked(int task) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005585 Slog.e(TAG, "moveTaskBackwards not yet implemented!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005586 }
5587
5588 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
5589 synchronized(this) {
5590 return getTaskForActivityLocked(token, onlyRoot);
5591 }
5592 }
5593
5594 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005595 final int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005596 TaskRecord lastTask = null;
5597 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005598 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
Dianne Hackbornbe707852011-11-11 14:32:10 -08005599 if (r.appToken == token) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005600 if (!onlyRoot || lastTask != r.task) {
5601 return r.task.taskId;
5602 }
5603 return -1;
5604 }
5605 lastTask = r.task;
5606 }
5607
5608 return -1;
5609 }
5610
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005611 public void finishOtherInstances(IBinder token, ComponentName className) {
5612 synchronized(this) {
5613 final long origId = Binder.clearCallingIdentity();
5614
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005615 int N = mMainStack.mHistory.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005616 TaskRecord lastTask = null;
5617 for (int i=0; i<N; i++) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005618 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005619 if (r.realActivity.equals(className)
Dianne Hackbornbe707852011-11-11 14:32:10 -08005620 && r.appToken != token && lastTask != r.task) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07005621 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005622 null, "others")) {
5623 i--;
5624 N--;
5625 }
5626 }
5627 lastTask = r.task;
5628 }
5629
5630 Binder.restoreCallingIdentity(origId);
5631 }
5632 }
5633
5634 // =========================================================
5635 // THUMBNAILS
5636 // =========================================================
5637
5638 public void reportThumbnail(IBinder token,
5639 Bitmap thumbnail, CharSequence description) {
5640 //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
5641 final long origId = Binder.clearCallingIdentity();
5642 sendPendingThumbnail(null, token, thumbnail, description, true);
5643 Binder.restoreCallingIdentity(origId);
5644 }
5645
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005646 final void sendPendingThumbnail(ActivityRecord r, IBinder token,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005647 Bitmap thumbnail, CharSequence description, boolean always) {
5648 TaskRecord task = null;
5649 ArrayList receivers = null;
5650
5651 //System.out.println("Send pending thumbnail: " + r);
5652
5653 synchronized(this) {
5654 if (r == null) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07005655 r = mMainStack.isInStackLocked(token);
5656 if (r == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005657 return;
5658 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005659 }
Dianne Hackbornf26fd992011-04-08 18:14:09 -07005660 if (thumbnail == null && r.thumbHolder != null) {
5661 thumbnail = r.thumbHolder.lastThumbnail;
5662 description = r.thumbHolder.lastDescription;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005663 }
5664 if (thumbnail == null && !always) {
5665 // If there is no thumbnail, and this entry is not actually
5666 // going away, then abort for now and pick up the next
5667 // thumbnail we get.
5668 return;
5669 }
5670 task = r.task;
5671
5672 int N = mPendingThumbnails.size();
5673 int i=0;
5674 while (i<N) {
5675 PendingThumbnailsRecord pr =
5676 (PendingThumbnailsRecord)mPendingThumbnails.get(i);
5677 //System.out.println("Looking in " + pr.pendingRecords);
5678 if (pr.pendingRecords.remove(r)) {
5679 if (receivers == null) {
5680 receivers = new ArrayList();
5681 }
5682 receivers.add(pr);
5683 if (pr.pendingRecords.size() == 0) {
5684 pr.finished = true;
5685 mPendingThumbnails.remove(i);
5686 N--;
5687 continue;
5688 }
5689 }
5690 i++;
5691 }
5692 }
5693
5694 if (receivers != null) {
5695 final int N = receivers.size();
5696 for (int i=0; i<N; i++) {
5697 try {
5698 PendingThumbnailsRecord pr =
5699 (PendingThumbnailsRecord)receivers.get(i);
5700 pr.receiver.newThumbnail(
5701 task != null ? task.taskId : -1, thumbnail, description);
5702 if (pr.finished) {
5703 pr.receiver.finished();
5704 }
5705 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005706 Slog.w(TAG, "Exception thrown when sending thumbnail", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005707 }
5708 }
5709 }
5710 }
5711
5712 // =========================================================
5713 // CONTENT PROVIDERS
5714 // =========================================================
5715
Jeff Brown10e89712011-07-08 18:52:57 -07005716 private final List<ProviderInfo> generateApplicationProvidersLocked(ProcessRecord app) {
5717 List<ProviderInfo> providers = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005718 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005719 providers = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005720 queryContentProviders(app.processName, app.info.uid,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005721 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005722 } catch (RemoteException ex) {
5723 }
5724 if (providers != null) {
5725 final int N = providers.size();
5726 for (int i=0; i<N; i++) {
5727 ProviderInfo cpi =
5728 (ProviderInfo)providers.get(i);
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07005729 ComponentName comp = new ComponentName(cpi.packageName, cpi.name);
5730 ContentProviderRecord cpr = mProvidersByClass.get(comp);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005731 if (cpr == null) {
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07005732 cpr = new ContentProviderRecord(cpi, app.info, comp);
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07005733 mProvidersByClass.put(comp, cpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005734 }
5735 app.pubProviders.put(cpi.name, cpr);
5736 app.addPackage(cpi.applicationInfo.packageName);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07005737 ensurePackageDexOpt(cpi.applicationInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005738 }
5739 }
5740 return providers;
5741 }
5742
5743 private final String checkContentProviderPermissionLocked(
Dianne Hackbornb424b632010-08-18 15:59:05 -07005744 ProviderInfo cpi, ProcessRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005745 final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
5746 final int callingUid = (r != null) ? r.info.uid : Binder.getCallingUid();
5747 if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005748 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005749 == PackageManager.PERMISSION_GRANTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005750 return null;
5751 }
5752 if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005753 cpi.applicationInfo.uid, cpi.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005754 == PackageManager.PERMISSION_GRANTED) {
5755 return null;
5756 }
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005757
5758 PathPermission[] pps = cpi.pathPermissions;
5759 if (pps != null) {
5760 int i = pps.length;
5761 while (i > 0) {
5762 i--;
5763 PathPermission pp = pps[i];
5764 if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005765 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackbornb424b632010-08-18 15:59:05 -07005766 == PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005767 return null;
5768 }
5769 if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005770 cpi.applicationInfo.uid, cpi.exported)
Dianne Hackborn2af632f2009-07-08 14:56:37 -07005771 == PackageManager.PERMISSION_GRANTED) {
5772 return null;
5773 }
5774 }
5775 }
5776
Dianne Hackbornb424b632010-08-18 15:59:05 -07005777 HashMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
5778 if (perms != null) {
5779 for (Map.Entry<Uri, UriPermission> uri : perms.entrySet()) {
5780 if (uri.getKey().getAuthority().equals(cpi.authority)) {
5781 return null;
5782 }
5783 }
5784 }
5785
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08005786 String msg;
5787 if (!cpi.exported) {
5788 msg = "Permission Denial: opening provider " + cpi.name
5789 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5790 + ", uid=" + callingUid + ") that is not exported from uid "
5791 + cpi.applicationInfo.uid;
5792 } else {
5793 msg = "Permission Denial: opening provider " + cpi.name
5794 + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
5795 + ", uid=" + callingUid + ") requires "
5796 + cpi.readPermission + " or " + cpi.writePermission;
5797 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005798 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005799 return msg;
5800 }
5801
Dianne Hackborn295e3c22011-08-25 13:19:08 -07005802 boolean incProviderCount(ProcessRecord r, ContentProviderRecord cpr) {
5803 if (r != null) {
5804 Integer cnt = r.conProviders.get(cpr);
5805 if (DEBUG_PROVIDER) Slog.v(TAG,
5806 "Adding provider requested by "
5807 + r.processName + " from process "
5808 + cpr.info.processName + ": " + cpr.name.flattenToShortString()
5809 + " cnt=" + (cnt == null ? 1 : cnt));
5810 if (cnt == null) {
5811 cpr.clients.add(r);
5812 r.conProviders.put(cpr, new Integer(1));
5813 return true;
5814 } else {
5815 r.conProviders.put(cpr, new Integer(cnt.intValue()+1));
5816 }
5817 } else {
5818 cpr.externals++;
5819 }
5820 return false;
5821 }
5822
5823 boolean decProviderCount(ProcessRecord r, ContentProviderRecord cpr) {
5824 if (r != null) {
5825 Integer cnt = r.conProviders.get(cpr);
5826 if (DEBUG_PROVIDER) Slog.v(TAG,
5827 "Removing provider requested by "
5828 + r.processName + " from process "
5829 + cpr.info.processName + ": " + cpr.name.flattenToShortString()
5830 + " cnt=" + cnt);
5831 if (cnt == null || cnt.intValue() <= 1) {
5832 cpr.clients.remove(r);
5833 r.conProviders.remove(cpr);
5834 return true;
5835 } else {
5836 r.conProviders.put(cpr, new Integer(cnt.intValue()-1));
5837 }
5838 } else {
5839 cpr.externals++;
5840 }
5841 return false;
5842 }
5843
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005844 private final ContentProviderHolder getContentProviderImpl(
5845 IApplicationThread caller, String name) {
5846 ContentProviderRecord cpr;
5847 ProviderInfo cpi = null;
5848
5849 synchronized(this) {
5850 ProcessRecord r = null;
5851 if (caller != null) {
5852 r = getRecordForAppLocked(caller);
5853 if (r == null) {
5854 throw new SecurityException(
5855 "Unable to find app for caller " + caller
5856 + " (pid=" + Binder.getCallingPid()
5857 + ") when getting content provider " + name);
5858 }
5859 }
5860
5861 // First check if this content provider has been published...
Dianne Hackborn860755f2010-06-03 18:47:52 -07005862 cpr = mProvidersByName.get(name);
Dianne Hackborn295e3c22011-08-25 13:19:08 -07005863 boolean providerRunning = cpr != null;
5864 if (providerRunning) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005865 cpi = cpr.info;
Dianne Hackbornb424b632010-08-18 15:59:05 -07005866 String msg;
5867 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5868 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005869 }
5870
5871 if (r != null && cpr.canRunHere(r)) {
5872 // This provider has been published or is in the process
5873 // of being published... but it is also allowed to run
5874 // in the caller's process, so don't make a connection
5875 // and just let the caller instantiate its own instance.
5876 if (cpr.provider != null) {
5877 // don't give caller the provider object, it needs
5878 // to make its own.
5879 cpr = new ContentProviderRecord(cpr);
5880 }
5881 return cpr;
5882 }
5883
5884 final long origId = Binder.clearCallingIdentity();
5885
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005886 // In this case the provider instance already exists, so we can
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005887 // return it right away.
Dianne Hackborn295e3c22011-08-25 13:19:08 -07005888 final boolean countChanged = incProviderCount(r, cpr);
5889 if (countChanged) {
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07005890 if (cpr.proc != null && r.setAdj <= ProcessList.PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn32907cf2010-06-10 17:50:20 -07005891 // If this is a perceptible app accessing the provider,
Dianne Hackborn906497c2010-05-10 15:57:38 -07005892 // make sure to count it as being accessed and thus
5893 // back up on the LRU list. This is good because
5894 // content providers are often expensive to start.
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07005895 updateLruProcessLocked(cpr.proc, false, true);
Dianne Hackborn906497c2010-05-10 15:57:38 -07005896 }
Dianne Hackborn6f86c0e2010-05-11 14:20:52 -07005897 }
5898
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07005899 if (cpr.proc != null) {
Dianne Hackborn295e3c22011-08-25 13:19:08 -07005900 if (false) {
5901 if (cpr.name.flattenToShortString().equals(
5902 "com.android.providers.calendar/.CalendarProvider2")) {
5903 Slog.v(TAG, "****************** KILLING "
5904 + cpr.name.flattenToShortString());
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07005905 Process.killProcess(cpr.proc.pid);
Dianne Hackborn295e3c22011-08-25 13:19:08 -07005906 }
5907 }
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07005908 boolean success = updateOomAdjLocked(cpr.proc);
Dianne Hackborn295e3c22011-08-25 13:19:08 -07005909 if (DEBUG_PROVIDER) Slog.i(TAG, "Adjust success: " + success);
5910 // NOTE: there is still a race here where a signal could be
5911 // pending on the process even though we managed to update its
5912 // adj level. Not sure what to do about this, but at least
5913 // the race is now smaller.
5914 if (!success) {
5915 // Uh oh... it looks like the provider's process
5916 // has been killed on us. We need to wait for a new
5917 // process to be started, and make sure its death
5918 // doesn't kill our process.
5919 Slog.i(TAG,
5920 "Existing provider " + cpr.name.flattenToShortString()
5921 + " is crashing; detaching " + r);
5922 boolean lastRef = decProviderCount(r, cpr);
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07005923 appDiedLocked(cpr.proc, cpr.proc.pid, cpr.proc.thread);
Dianne Hackborn295e3c22011-08-25 13:19:08 -07005924 if (!lastRef) {
5925 // This wasn't the last ref our process had on
5926 // the provider... we have now been killed, bail.
5927 return null;
5928 }
5929 providerRunning = false;
5930 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005931 }
5932
5933 Binder.restoreCallingIdentity(origId);
Dianne Hackborn295e3c22011-08-25 13:19:08 -07005934 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005935
Dianne Hackborn295e3c22011-08-25 13:19:08 -07005936 if (!providerRunning) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005937 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005938 cpi = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07005939 resolveContentProvider(name,
5940 STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005941 } catch (RemoteException ex) {
5942 }
5943 if (cpi == null) {
5944 return null;
5945 }
5946
Dianne Hackbornb424b632010-08-18 15:59:05 -07005947 String msg;
5948 if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) {
5949 throw new SecurityException(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005950 }
5951
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07005952 if (!mProcessesReady && !mDidUpdate && !mWaitingUpdate
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08005953 && !cpi.processName.equals("system")) {
5954 // If this content provider does not run in the system
5955 // process, and the system is not yet ready to run other
5956 // processes, then fail fast instead of hanging.
5957 throw new IllegalArgumentException(
5958 "Attempt to launch content provider before system ready");
5959 }
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07005960
5961 ComponentName comp = new ComponentName(cpi.packageName, cpi.name);
5962 cpr = mProvidersByClass.get(comp);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005963 final boolean firstClass = cpr == null;
5964 if (firstClass) {
5965 try {
5966 ApplicationInfo ai =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07005967 AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005968 getApplicationInfo(
5969 cpi.applicationInfo.packageName,
Dianne Hackborn1655be42009-05-08 14:29:01 -07005970 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005971 if (ai == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005972 Slog.w(TAG, "No package info for content provider "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005973 + cpi.name);
5974 return null;
5975 }
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07005976 cpr = new ContentProviderRecord(cpi, ai, comp);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005977 } catch (RemoteException ex) {
5978 // pm is in same process, this will never happen.
5979 }
5980 }
5981
5982 if (r != null && cpr.canRunHere(r)) {
5983 // If this is a multiprocess provider, then just return its
5984 // info and allow the caller to instantiate it. Only do
5985 // this if the provider is the same user as the caller's
5986 // process, or can run as root (so can be in any process).
5987 return cpr;
5988 }
5989
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005990 if (DEBUG_PROVIDER) {
5991 RuntimeException e = new RuntimeException("here");
Joe Onorato8a9b2202010-02-26 18:56:32 -08005992 Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + r.info.uid
Dianne Hackborna1e989b2009-09-01 19:54:29 -07005993 + " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005994 }
5995
5996 // This is single process, and our app is now connecting to it.
5997 // See if we are already in the process of launching this
5998 // provider.
5999 final int N = mLaunchingProviders.size();
6000 int i;
6001 for (i=0; i<N; i++) {
6002 if (mLaunchingProviders.get(i) == cpr) {
6003 break;
6004 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006005 }
6006
6007 // If the provider is not already being launched, then get it
6008 // started.
6009 if (i >= N) {
6010 final long origId = Binder.clearCallingIdentity();
Dianne Hackborne7f97212011-02-24 14:40:20 -08006011
6012 try {
6013 // Content provider is now in use, its package can't be stopped.
6014 try {
6015 AppGlobals.getPackageManager().setPackageStoppedState(
6016 cpr.appInfo.packageName, false);
6017 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08006018 } catch (IllegalArgumentException e) {
6019 Slog.w(TAG, "Failed trying to unstop package "
6020 + cpr.appInfo.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08006021 }
6022
6023 ProcessRecord proc = startProcessLocked(cpi.processName,
6024 cpr.appInfo, false, 0, "content provider",
6025 new ComponentName(cpi.applicationInfo.packageName,
6026 cpi.name), false);
6027 if (proc == null) {
6028 Slog.w(TAG, "Unable to launch app "
6029 + cpi.applicationInfo.packageName + "/"
6030 + cpi.applicationInfo.uid + " for provider "
6031 + name + ": process is bad");
6032 return null;
6033 }
6034 cpr.launchingApp = proc;
6035 mLaunchingProviders.add(cpr);
6036 } finally {
6037 Binder.restoreCallingIdentity(origId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006038 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006039 }
6040
6041 // Make sure the provider is published (the same provider class
6042 // may be published under multiple names).
6043 if (firstClass) {
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07006044 mProvidersByClass.put(comp, cpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006045 }
6046 mProvidersByName.put(name, cpr);
Dianne Hackborn295e3c22011-08-25 13:19:08 -07006047 incProviderCount(r, cpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006048 }
6049 }
6050
6051 // Wait for the provider to be published...
6052 synchronized (cpr) {
6053 while (cpr.provider == null) {
6054 if (cpr.launchingApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006055 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006056 + cpi.applicationInfo.packageName + "/"
6057 + cpi.applicationInfo.uid + " for provider "
6058 + name + ": launching app became null");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006059 EventLog.writeEvent(EventLogTags.AM_PROVIDER_LOST_PROCESS,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006060 cpi.applicationInfo.packageName,
6061 cpi.applicationInfo.uid, name);
6062 return null;
6063 }
6064 try {
6065 cpr.wait();
6066 } catch (InterruptedException ex) {
6067 }
6068 }
6069 }
6070 return cpr;
6071 }
6072
6073 public final ContentProviderHolder getContentProvider(
6074 IApplicationThread caller, String name) {
6075 if (caller == null) {
6076 String msg = "null IApplicationThread when getting content provider "
6077 + name;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006078 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006079 throw new SecurityException(msg);
6080 }
6081
6082 return getContentProviderImpl(caller, name);
6083 }
6084
6085 private ContentProviderHolder getContentProviderExternal(String name) {
6086 return getContentProviderImpl(null, name);
6087 }
6088
6089 /**
6090 * Drop a content provider from a ProcessRecord's bookkeeping
6091 * @param cpr
6092 */
6093 public void removeContentProvider(IApplicationThread caller, String name) {
6094 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006095 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006096 if(cpr == null) {
Dianne Hackborna1e989b2009-09-01 19:54:29 -07006097 // remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08006098 if (DEBUG_PROVIDER) Slog.v(TAG, name +
Dianne Hackborna1e989b2009-09-01 19:54:29 -07006099 " provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006100 return;
6101 }
6102 final ProcessRecord r = getRecordForAppLocked(caller);
6103 if (r == null) {
6104 throw new SecurityException(
6105 "Unable to find app for caller " + caller +
6106 " when removing content provider " + name);
6107 }
6108 //update content provider record entry info
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07006109 ComponentName comp = new ComponentName(cpr.info.packageName, cpr.info.name);
6110 ContentProviderRecord localCpr = mProvidersByClass.get(comp);
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07006111 if (localCpr.proc == r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006112 //should not happen. taken care of as a local provider
Joe Onorato8a9b2202010-02-26 18:56:32 -08006113 Slog.w(TAG, "removeContentProvider called on local provider: "
Dianne Hackborna1e989b2009-09-01 19:54:29 -07006114 + cpr.info.name + " in process " + r.processName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006115 return;
6116 } else {
Dianne Hackborn295e3c22011-08-25 13:19:08 -07006117 if (decProviderCount(r, localCpr)) {
6118 updateOomAdjLocked();
Dianne Hackborn0c3154d2009-10-06 17:18:05 -07006119 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006120 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006121 }
6122 }
6123
6124 private void removeContentProviderExternal(String name) {
6125 synchronized (this) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07006126 ContentProviderRecord cpr = mProvidersByName.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006127 if(cpr == null) {
6128 //remove from mProvidersByClass
Joe Onorato8a9b2202010-02-26 18:56:32 -08006129 if(localLOGV) Slog.v(TAG, name+" content provider not found in providers list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006130 return;
6131 }
6132
6133 //update content provider record entry info
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07006134 ComponentName comp = new ComponentName(cpr.info.packageName, cpr.info.name);
6135 ContentProviderRecord localCpr = mProvidersByClass.get(comp);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006136 localCpr.externals--;
6137 if (localCpr.externals < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006138 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006139 }
6140 updateOomAdjLocked();
6141 }
6142 }
6143
6144 public final void publishContentProviders(IApplicationThread caller,
6145 List<ContentProviderHolder> providers) {
6146 if (providers == null) {
6147 return;
6148 }
6149
6150 synchronized(this) {
6151 final ProcessRecord r = getRecordForAppLocked(caller);
6152 if (r == null) {
6153 throw new SecurityException(
6154 "Unable to find app for caller " + caller
6155 + " (pid=" + Binder.getCallingPid()
6156 + ") when publishing content providers");
6157 }
6158
6159 final long origId = Binder.clearCallingIdentity();
6160
6161 final int N = providers.size();
6162 for (int i=0; i<N; i++) {
6163 ContentProviderHolder src = providers.get(i);
6164 if (src == null || src.info == null || src.provider == null) {
6165 continue;
6166 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07006167 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006168 if (dst != null) {
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07006169 ComponentName comp = new ComponentName(dst.info.packageName, dst.info.name);
6170 mProvidersByClass.put(comp, dst);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006171 String names[] = dst.info.authority.split(";");
6172 for (int j = 0; j < names.length; j++) {
6173 mProvidersByName.put(names[j], dst);
6174 }
6175
6176 int NL = mLaunchingProviders.size();
6177 int j;
6178 for (j=0; j<NL; j++) {
6179 if (mLaunchingProviders.get(j) == dst) {
6180 mLaunchingProviders.remove(j);
6181 j--;
6182 NL--;
6183 }
6184 }
6185 synchronized (dst) {
6186 dst.provider = src.provider;
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07006187 dst.proc = r;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006188 dst.notifyAll();
6189 }
6190 updateOomAdjLocked(r);
6191 }
6192 }
6193
6194 Binder.restoreCallingIdentity(origId);
6195 }
6196 }
6197
6198 public static final void installSystemProviders() {
Jeff Brown10e89712011-07-08 18:52:57 -07006199 List<ProviderInfo> providers;
Josh Bartel2ecce342010-02-25 10:55:48 -06006200 synchronized (mSelf) {
6201 ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);
6202 providers = mSelf.generateApplicationProvidersLocked(app);
Dianne Hackborn5c83a5f2010-03-12 16:46:46 -08006203 if (providers != null) {
6204 for (int i=providers.size()-1; i>=0; i--) {
6205 ProviderInfo pi = (ProviderInfo)providers.get(i);
6206 if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
6207 Slog.w(TAG, "Not installing system proc provider " + pi.name
6208 + ": not system .apk");
6209 providers.remove(i);
6210 }
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -08006211 }
6212 }
6213 }
Josh Bartel2ecce342010-02-25 10:55:48 -06006214 if (providers != null) {
6215 mSystemThread.installSystemProviders(providers);
6216 }
Svetoslav Ganov54d068e2011-03-02 12:58:40 -08006217
6218 mSelf.mCoreSettingsObserver = new CoreSettingsObserver(mSelf);
Mark Brophyc6350272011-08-05 16:16:39 +01006219
6220 mSelf.mUsageStatsService.monitorPackages();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006221 }
6222
Dianne Hackborncca1f0e2010-09-26 18:34:53 -07006223 /**
6224 * Allows app to retrieve the MIME type of a URI without having permission
6225 * to access its content provider.
6226 *
6227 * CTS tests for this functionality can be run with "runtest cts-appsecurity".
6228 *
6229 * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
6230 * src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
6231 */
6232 public String getProviderMimeType(Uri uri) {
6233 final String name = uri.getAuthority();
6234 final long ident = Binder.clearCallingIdentity();
6235 ContentProviderHolder holder = null;
6236
6237 try {
6238 holder = getContentProviderExternal(name);
6239 if (holder != null) {
6240 return holder.provider.getType(uri);
6241 }
6242 } catch (RemoteException e) {
6243 Log.w(TAG, "Content provider dead retrieving " + uri, e);
6244 return null;
6245 } finally {
6246 if (holder != null) {
6247 removeContentProviderExternal(name);
6248 }
6249 Binder.restoreCallingIdentity(ident);
6250 }
6251
6252 return null;
6253 }
6254
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006255 // =========================================================
6256 // GLOBAL MANAGEMENT
6257 // =========================================================
6258
6259 final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
6260 ApplicationInfo info, String customProcess) {
6261 String proc = customProcess != null ? customProcess : info.processName;
6262 BatteryStatsImpl.Uid.Proc ps = null;
6263 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
6264 synchronized (stats) {
6265 ps = stats.getProcessStatsLocked(info.uid, proc);
6266 }
6267 return new ProcessRecord(ps, thread, info, proc);
6268 }
6269
6270 final ProcessRecord addAppLocked(ApplicationInfo info) {
6271 ProcessRecord app = getProcessRecordLocked(info.processName, info.uid);
6272
6273 if (app == null) {
6274 app = newProcessRecordLocked(null, info, null);
6275 mProcessNames.put(info.processName, info.uid, app);
Dianne Hackborndd71fc82009-12-16 19:24:32 -08006276 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006277 }
6278
Dianne Hackborne7f97212011-02-24 14:40:20 -08006279 // This package really, really can not be stopped.
6280 try {
6281 AppGlobals.getPackageManager().setPackageStoppedState(
6282 info.packageName, false);
6283 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -08006284 } catch (IllegalArgumentException e) {
6285 Slog.w(TAG, "Failed trying to unstop package "
6286 + info.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08006287 }
6288
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006289 if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
6290 == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
6291 app.persistent = true;
Dianne Hackborne02c88a2011-10-28 13:58:15 -07006292 app.maxAdj = ProcessList.PERSISTENT_PROC_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006293 }
6294 if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
6295 mPersistentStartingProcesses.add(app);
6296 startProcessLocked(app, "added application", app.processName);
6297 }
6298
6299 return app;
6300 }
6301
6302 public void unhandledBack() {
6303 enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
6304 "unhandledBack()");
6305
6306 synchronized(this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006307 int count = mMainStack.mHistory.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08006308 if (DEBUG_SWITCH) Slog.d(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006309 TAG, "Performing unhandledBack(): stack size = " + count);
6310 if (count > 1) {
6311 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006312 mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006313 count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
6314 Binder.restoreCallingIdentity(origId);
6315 }
6316 }
6317 }
6318
6319 public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
6320 String name = uri.getAuthority();
6321 ContentProviderHolder cph = getContentProviderExternal(name);
6322 ParcelFileDescriptor pfd = null;
6323 if (cph != null) {
6324 // We record the binder invoker's uid in thread-local storage before
6325 // going to the content provider to open the file. Later, in the code
6326 // that handles all permissions checks, we look for this uid and use
6327 // that rather than the Activity Manager's own uid. The effect is that
6328 // we do the check against the caller's permissions even though it looks
6329 // to the content provider like the Activity Manager itself is making
6330 // the request.
6331 sCallerIdentity.set(new Identity(
6332 Binder.getCallingPid(), Binder.getCallingUid()));
6333 try {
6334 pfd = cph.provider.openFile(uri, "r");
6335 } catch (FileNotFoundException e) {
6336 // do nothing; pfd will be returned null
6337 } finally {
6338 // Ensure that whatever happens, we clean up the identity state
6339 sCallerIdentity.remove();
6340 }
6341
6342 // We've got the fd now, so we're done with the provider.
6343 removeContentProviderExternal(name);
6344 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006345 Slog.d(TAG, "Failed to get provider for authority '" + name + "'");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006346 }
6347 return pfd;
6348 }
6349
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006350 // Actually is sleeping or shutting down or whatever else in the future
6351 // is an inactive state.
6352 public boolean isSleeping() {
6353 return mSleeping || mShuttingDown;
6354 }
6355
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006356 public void goingToSleep() {
6357 synchronized(this) {
6358 mSleeping = true;
6359 mWindowManager.setEventDispatching(false);
6360
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006361 mMainStack.stopIfSleepingLocked();
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07006362
6363 // Initialize the wake times of all processes.
Dianne Hackborn287952c2010-09-22 22:34:31 -07006364 checkExcessivePowerUsageLocked(false);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -07006365 mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
6366 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Dianne Hackborn287952c2010-09-22 22:34:31 -07006367 mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006368 }
6369 }
6370
Dianne Hackborn55280a92009-05-07 15:53:46 -07006371 public boolean shutdown(int timeout) {
6372 if (checkCallingPermission(android.Manifest.permission.SHUTDOWN)
6373 != PackageManager.PERMISSION_GRANTED) {
6374 throw new SecurityException("Requires permission "
6375 + android.Manifest.permission.SHUTDOWN);
6376 }
6377
6378 boolean timedout = false;
6379
6380 synchronized(this) {
6381 mShuttingDown = true;
6382 mWindowManager.setEventDispatching(false);
6383
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006384 if (mMainStack.mResumedActivity != null) {
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006385 mMainStack.stopIfSleepingLocked();
Dianne Hackborn55280a92009-05-07 15:53:46 -07006386 final long endTime = System.currentTimeMillis() + timeout;
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006387 while (mMainStack.mResumedActivity != null
6388 || mMainStack.mPausingActivity != null) {
Dianne Hackborn55280a92009-05-07 15:53:46 -07006389 long delay = endTime - System.currentTimeMillis();
6390 if (delay <= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006391 Slog.w(TAG, "Activity manager shutdown timed out");
Dianne Hackborn55280a92009-05-07 15:53:46 -07006392 timedout = true;
6393 break;
6394 }
6395 try {
6396 this.wait();
6397 } catch (InterruptedException e) {
6398 }
6399 }
6400 }
6401 }
6402
6403 mUsageStatsService.shutdown();
6404 mBatteryStatsService.shutdown();
6405
6406 return timedout;
6407 }
6408
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006409 public final void activitySlept(IBinder token) {
6410 if (localLOGV) Slog.v(
6411 TAG, "Activity slept: token=" + token);
6412
6413 ActivityRecord r = null;
6414
6415 final long origId = Binder.clearCallingIdentity();
6416
6417 synchronized (this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07006418 r = mMainStack.isInStackLocked(token);
6419 if (r != null) {
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006420 mMainStack.activitySleptLocked(r);
6421 }
6422 }
6423
6424 Binder.restoreCallingIdentity(origId);
6425 }
6426
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006427 public void wakingUp() {
6428 synchronized(this) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006429 mWindowManager.setEventDispatching(true);
6430 mSleeping = false;
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08006431 mMainStack.awakeFromSleepingLocked();
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006432 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006433 }
6434 }
6435
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006436 public void stopAppSwitches() {
6437 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
6438 != PackageManager.PERMISSION_GRANTED) {
6439 throw new SecurityException("Requires permission "
6440 + android.Manifest.permission.STOP_APP_SWITCHES);
6441 }
6442
6443 synchronized(this) {
6444 mAppSwitchesAllowedTime = SystemClock.uptimeMillis()
6445 + APP_SWITCH_DELAY_TIME;
6446 mDidAppSwitch = false;
6447 mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
6448 Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
6449 mHandler.sendMessageDelayed(msg, APP_SWITCH_DELAY_TIME);
6450 }
6451 }
6452
6453 public void resumeAppSwitches() {
6454 if (checkCallingPermission(android.Manifest.permission.STOP_APP_SWITCHES)
6455 != PackageManager.PERMISSION_GRANTED) {
6456 throw new SecurityException("Requires permission "
6457 + android.Manifest.permission.STOP_APP_SWITCHES);
6458 }
6459
6460 synchronized(this) {
6461 // Note that we don't execute any pending app switches... we will
6462 // let those wait until either the timeout, or the next start
6463 // activity request.
6464 mAppSwitchesAllowedTime = 0;
6465 }
6466 }
6467
6468 boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid,
6469 String name) {
6470 if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
6471 return true;
6472 }
6473
6474 final int perm = checkComponentPermission(
6475 android.Manifest.permission.STOP_APP_SWITCHES, callingPid,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -08006476 callingUid, -1, true);
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006477 if (perm == PackageManager.PERMISSION_GRANTED) {
6478 return true;
6479 }
6480
Joe Onorato8a9b2202010-02-26 18:56:32 -08006481 Slog.w(TAG, name + " request from " + callingUid + " stopped");
Dianne Hackborn95fc68f2009-05-19 18:37:45 -07006482 return false;
6483 }
6484
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006485 public void setDebugApp(String packageName, boolean waitForDebugger,
6486 boolean persistent) {
6487 enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
6488 "setDebugApp()");
6489
6490 // Note that this is not really thread safe if there are multiple
6491 // callers into it at the same time, but that's not a situation we
6492 // care about.
6493 if (persistent) {
6494 final ContentResolver resolver = mContext.getContentResolver();
6495 Settings.System.putString(
6496 resolver, Settings.System.DEBUG_APP,
6497 packageName);
6498 Settings.System.putInt(
6499 resolver, Settings.System.WAIT_FOR_DEBUGGER,
6500 waitForDebugger ? 1 : 0);
6501 }
6502
6503 synchronized (this) {
6504 if (!persistent) {
6505 mOrigDebugApp = mDebugApp;
6506 mOrigWaitForDebugger = mWaitForDebugger;
6507 }
6508 mDebugApp = packageName;
6509 mWaitForDebugger = waitForDebugger;
6510 mDebugTransient = !persistent;
6511 if (packageName != null) {
6512 final long origId = Binder.clearCallingIdentity();
Christopher Tate3dacd842011-08-19 14:56:15 -07006513 forceStopPackageLocked(packageName, -1, false, false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006514 Binder.restoreCallingIdentity(origId);
6515 }
6516 }
6517 }
6518
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07006519 void setProfileApp(ApplicationInfo app, String processName, String profileFile,
6520 ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
6521 synchronized (this) {
6522 boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
6523 if (!isDebuggable) {
6524 if ((app.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
6525 throw new SecurityException("Process not debuggable: " + app.packageName);
6526 }
6527 }
6528 mProfileApp = processName;
6529 mProfileFile = profileFile;
6530 if (mProfileFd != null) {
6531 try {
6532 mProfileFd.close();
6533 } catch (IOException e) {
6534 }
6535 mProfileFd = null;
6536 }
6537 mProfileFd = profileFd;
6538 mProfileType = 0;
6539 mAutoStopProfiler = autoStopProfiler;
6540 }
6541 }
6542
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006543 public void setAlwaysFinish(boolean enabled) {
6544 enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
6545 "setAlwaysFinish()");
6546
6547 Settings.System.putInt(
6548 mContext.getContentResolver(),
6549 Settings.System.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
6550
6551 synchronized (this) {
6552 mAlwaysFinishActivities = enabled;
6553 }
6554 }
6555
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006556 public void setActivityController(IActivityController controller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006557 enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006558 "setActivityController()");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006559 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006560 mController = controller;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006561 }
6562 }
6563
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08006564 public boolean isUserAMonkey() {
6565 // For now the fact that there is a controller implies
6566 // we have a monkey.
6567 synchronized (this) {
6568 return mController != null;
6569 }
6570 }
6571
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006572 public void registerActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06006573 synchronized (this) {
6574 mWatchers.register(watcher);
6575 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006576 }
6577
6578 public void unregisterActivityWatcher(IActivityWatcher watcher) {
Josh Bartel2ecce342010-02-25 10:55:48 -06006579 synchronized (this) {
6580 mWatchers.unregister(watcher);
6581 }
Dianne Hackbornb06ea702009-07-13 13:07:51 -07006582 }
6583
Jeff Sharkeya4620792011-05-20 15:29:23 -07006584 public void registerProcessObserver(IProcessObserver observer) {
6585 mProcessObservers.register(observer);
6586 }
6587
6588 public void unregisterProcessObserver(IProcessObserver observer) {
6589 mProcessObservers.unregister(observer);
6590 }
6591
Daniel Sandler69a48172010-06-23 16:29:36 -04006592 public void setImmersive(IBinder token, boolean immersive) {
6593 synchronized(this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07006594 ActivityRecord r = mMainStack.isInStackLocked(token);
6595 if (r == null) {
Daniel Sandler69a48172010-06-23 16:29:36 -04006596 throw new IllegalArgumentException();
6597 }
Daniel Sandler69a48172010-06-23 16:29:36 -04006598 r.immersive = immersive;
6599 }
6600 }
6601
6602 public boolean isImmersive(IBinder token) {
6603 synchronized (this) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -07006604 ActivityRecord r = mMainStack.isInStackLocked(token);
6605 if (r == null) {
Daniel Sandler69a48172010-06-23 16:29:36 -04006606 throw new IllegalArgumentException();
6607 }
Daniel Sandler69a48172010-06-23 16:29:36 -04006608 return r.immersive;
6609 }
6610 }
6611
6612 public boolean isTopActivityImmersive() {
6613 synchronized (this) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07006614 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Daniel Sandler69a48172010-06-23 16:29:36 -04006615 return (r != null) ? r.immersive : false;
6616 }
6617 }
6618
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006619 public final void enterSafeMode() {
6620 synchronized(this) {
6621 // It only makes sense to do this before the system is ready
6622 // and started launching other packages.
6623 if (!mSystemReady) {
6624 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006625 AppGlobals.getPackageManager().enterSafeMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006626 } catch (RemoteException e) {
6627 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006628 }
6629 }
6630 }
6631
Jeff Brownb09abc12011-01-13 21:08:27 -08006632 public final void showSafeModeOverlay() {
6633 View v = LayoutInflater.from(mContext).inflate(
6634 com.android.internal.R.layout.safe_mode, null);
6635 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
6636 lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
6637 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
6638 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
6639 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
6640 lp.format = v.getBackground().getOpacity();
6641 lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
6642 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
6643 ((WindowManager)mContext.getSystemService(
6644 Context.WINDOW_SERVICE)).addView(v, lp);
6645 }
6646
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006647 public void noteWakeupAlarm(IIntentSender sender) {
6648 if (!(sender instanceof PendingIntentRecord)) {
6649 return;
6650 }
6651 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
6652 synchronized (stats) {
6653 if (mBatteryStatsService.isOnBattery()) {
6654 mBatteryStatsService.enforceCallingPermission();
6655 PendingIntentRecord rec = (PendingIntentRecord)sender;
6656 int MY_UID = Binder.getCallingUid();
6657 int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
6658 BatteryStatsImpl.Uid.Pkg pkg =
6659 stats.getPackageStatsLocked(uid, rec.key.packageName);
6660 pkg.incWakeupsLocked();
6661 }
6662 }
6663 }
6664
Dianne Hackborn64825172011-03-02 21:32:58 -08006665 public boolean killPids(int[] pids, String pReason, boolean secure) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006666 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006667 throw new SecurityException("killPids only available to the system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006668 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006669 String reason = (pReason == null) ? "Unknown" : pReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006670 // XXX Note: don't acquire main activity lock here, because the window
6671 // manager calls in with its locks held.
6672
6673 boolean killed = false;
6674 synchronized (mPidsSelfLocked) {
6675 int[] types = new int[pids.length];
6676 int worstType = 0;
6677 for (int i=0; i<pids.length; i++) {
6678 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6679 if (proc != null) {
6680 int type = proc.setAdj;
6681 types[i] = type;
6682 if (type > worstType) {
6683 worstType = type;
6684 }
6685 }
6686 }
6687
Dianne Hackborn64825172011-03-02 21:32:58 -08006688 // If the worst oom_adj is somewhere in the hidden proc LRU range,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006689 // then constrain it so we will kill all hidden procs.
Dianne Hackborne02c88a2011-10-28 13:58:15 -07006690 if (worstType < ProcessList.HIDDEN_APP_MAX_ADJ
6691 && worstType > ProcessList.HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn7d608422011-08-07 16:24:18 -07006692 worstType = ProcessList.HIDDEN_APP_MIN_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006693 }
Dianne Hackborn64825172011-03-02 21:32:58 -08006694
6695 // If this is not a secure call, don't let it kill processes that
6696 // are important.
Dianne Hackborne02c88a2011-10-28 13:58:15 -07006697 if (!secure && worstType < ProcessList.SERVICE_ADJ) {
6698 worstType = ProcessList.SERVICE_ADJ;
Dianne Hackborn64825172011-03-02 21:32:58 -08006699 }
6700
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006701 Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006702 for (int i=0; i<pids.length; i++) {
6703 ProcessRecord proc = mPidsSelfLocked.get(pids[i]);
6704 if (proc == null) {
6705 continue;
6706 }
6707 int adj = proc.setAdj;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006708 if (adj >= worstType && !proc.killedBackground) {
Dianne Hackborn8633e682010-04-22 16:03:41 -07006709 Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07006710 EventLog.writeEvent(EventLogTags.AM_KILL, proc.pid,
6711 proc.processName, adj, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006712 killed = true;
Dianne Hackborn906497c2010-05-10 15:57:38 -07006713 proc.killedBackground = true;
6714 Process.killProcessQuiet(pids[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006715 }
6716 }
6717 }
6718 return killed;
6719 }
6720
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006721 public final void startRunning(String pkg, String cls, String action,
6722 String data) {
6723 synchronized(this) {
6724 if (mStartRunning) {
6725 return;
6726 }
6727 mStartRunning = true;
6728 mTopComponent = pkg != null && cls != null
6729 ? new ComponentName(pkg, cls) : null;
6730 mTopAction = action != null ? action : Intent.ACTION_MAIN;
6731 mTopData = data;
6732 if (!mSystemReady) {
6733 return;
6734 }
6735 }
6736
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006737 systemReady(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006738 }
6739
6740 private void retrieveSettings() {
6741 final ContentResolver resolver = mContext.getContentResolver();
6742 String debugApp = Settings.System.getString(
6743 resolver, Settings.System.DEBUG_APP);
6744 boolean waitForDebugger = Settings.System.getInt(
6745 resolver, Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
6746 boolean alwaysFinishActivities = Settings.System.getInt(
6747 resolver, Settings.System.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
6748
6749 Configuration configuration = new Configuration();
6750 Settings.System.getConfiguration(resolver, configuration);
6751
6752 synchronized (this) {
6753 mDebugApp = mOrigDebugApp = debugApp;
6754 mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
6755 mAlwaysFinishActivities = alwaysFinishActivities;
6756 // This happens before any activities are started, so we can
6757 // change mConfiguration in-place.
Dianne Hackborn813075a62011-11-14 17:45:19 -08006758 updateConfigurationLocked(configuration, null, false, true);
Joe Onorato8a9b2202010-02-26 18:56:32 -08006759 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006760 }
6761 }
6762
6763 public boolean testIsSystemReady() {
6764 // no need to synchronize(this) just to read & return the value
6765 return mSystemReady;
6766 }
6767
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006768 private static File getCalledPreBootReceiversFile() {
6769 File dataDir = Environment.getDataDirectory();
6770 File systemDir = new File(dataDir, "system");
6771 File fname = new File(systemDir, "called_pre_boots.dat");
6772 return fname;
6773 }
Dianne Hackborn661cd522011-08-22 00:26:20 -07006774
6775 static final int LAST_DONE_VERSION = 10000;
6776
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006777 private static ArrayList<ComponentName> readLastDonePreBootReceivers() {
6778 ArrayList<ComponentName> lastDoneReceivers = new ArrayList<ComponentName>();
6779 File file = getCalledPreBootReceiversFile();
6780 FileInputStream fis = null;
6781 try {
6782 fis = new FileInputStream(file);
6783 DataInputStream dis = new DataInputStream(new BufferedInputStream(fis, 2048));
Dianne Hackborn661cd522011-08-22 00:26:20 -07006784 int fvers = dis.readInt();
6785 if (fvers == LAST_DONE_VERSION) {
6786 String vers = dis.readUTF();
6787 String codename = dis.readUTF();
6788 String build = dis.readUTF();
6789 if (android.os.Build.VERSION.RELEASE.equals(vers)
6790 && android.os.Build.VERSION.CODENAME.equals(codename)
6791 && android.os.Build.VERSION.INCREMENTAL.equals(build)) {
6792 int num = dis.readInt();
6793 while (num > 0) {
6794 num--;
6795 String pkg = dis.readUTF();
6796 String cls = dis.readUTF();
6797 lastDoneReceivers.add(new ComponentName(pkg, cls));
6798 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006799 }
6800 }
6801 } catch (FileNotFoundException e) {
6802 } catch (IOException e) {
6803 Slog.w(TAG, "Failure reading last done pre-boot receivers", e);
6804 } finally {
6805 if (fis != null) {
6806 try {
6807 fis.close();
6808 } catch (IOException e) {
6809 }
6810 }
6811 }
6812 return lastDoneReceivers;
6813 }
6814
6815 private static void writeLastDonePreBootReceivers(ArrayList<ComponentName> list) {
6816 File file = getCalledPreBootReceiversFile();
6817 FileOutputStream fos = null;
6818 DataOutputStream dos = null;
6819 try {
6820 Slog.i(TAG, "Writing new set of last done pre-boot receivers...");
6821 fos = new FileOutputStream(file);
6822 dos = new DataOutputStream(new BufferedOutputStream(fos, 2048));
Dianne Hackborn661cd522011-08-22 00:26:20 -07006823 dos.writeInt(LAST_DONE_VERSION);
6824 dos.writeUTF(android.os.Build.VERSION.RELEASE);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006825 dos.writeUTF(android.os.Build.VERSION.CODENAME);
Dianne Hackborn661cd522011-08-22 00:26:20 -07006826 dos.writeUTF(android.os.Build.VERSION.INCREMENTAL);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006827 dos.writeInt(list.size());
6828 for (int i=0; i<list.size(); i++) {
6829 dos.writeUTF(list.get(i).getPackageName());
6830 dos.writeUTF(list.get(i).getClassName());
6831 }
6832 } catch (IOException e) {
6833 Slog.w(TAG, "Failure writing last done pre-boot receivers", e);
6834 file.delete();
6835 } finally {
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07006836 FileUtils.sync(fos);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006837 if (dos != null) {
6838 try {
6839 dos.close();
6840 } catch (IOException e) {
6841 // TODO Auto-generated catch block
6842 e.printStackTrace();
6843 }
6844 }
6845 }
6846 }
6847
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006848 public void systemReady(final Runnable goingCallback) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006849 synchronized(this) {
6850 if (mSystemReady) {
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07006851 if (goingCallback != null) goingCallback.run();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006852 return;
6853 }
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006854
6855 // Check to see if there are any update receivers to run.
6856 if (!mDidUpdate) {
6857 if (mWaitingUpdate) {
6858 return;
6859 }
6860 Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
6861 List<ResolveInfo> ris = null;
6862 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07006863 ris = AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006864 intent, null, 0);
6865 } catch (RemoteException e) {
6866 }
6867 if (ris != null) {
6868 for (int i=ris.size()-1; i>=0; i--) {
6869 if ((ris.get(i).activityInfo.applicationInfo.flags
6870 &ApplicationInfo.FLAG_SYSTEM) == 0) {
6871 ris.remove(i);
6872 }
6873 }
6874 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006875
6876 ArrayList<ComponentName> lastDoneReceivers = readLastDonePreBootReceivers();
6877
6878 final ArrayList<ComponentName> doneReceivers = new ArrayList<ComponentName>();
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006879 for (int i=0; i<ris.size(); i++) {
6880 ActivityInfo ai = ris.get(i).activityInfo;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006881 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6882 if (lastDoneReceivers.contains(comp)) {
6883 ris.remove(i);
6884 i--;
6885 }
6886 }
Dianne Hackborn29aae6f2011-08-18 18:30:09 -07006887
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006888 for (int i=0; i<ris.size(); i++) {
6889 ActivityInfo ai = ris.get(i).activityInfo;
6890 ComponentName comp = new ComponentName(ai.packageName, ai.name);
6891 doneReceivers.add(comp);
6892 intent.setComponent(comp);
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006893 IIntentReceiver finisher = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -08006894 if (i == ris.size()-1) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006895 finisher = new IIntentReceiver.Stub() {
6896 public void performReceive(Intent intent, int resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -07006897 String data, Bundle extras, boolean ordered,
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006898 boolean sticky) {
6899 // The raw IIntentReceiver interface is called
6900 // with the AM lock held, so redispatch to
6901 // execute our code without the lock.
6902 mHandler.post(new Runnable() {
6903 public void run() {
6904 synchronized (ActivityManagerService.this) {
6905 mDidUpdate = true;
6906 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006907 writeLastDonePreBootReceivers(doneReceivers);
Dianne Hackborn661cd522011-08-22 00:26:20 -07006908 showBootMessage(mContext.getText(
6909 R.string.android_upgrading_complete),
6910 false);
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -07006911 systemReady(goingCallback);
6912 }
6913 });
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006914 }
6915 };
6916 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006917 Slog.i(TAG, "Sending system update to: " + intent.getComponent());
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006918 broadcastIntentLocked(null, null, intent, null, finisher,
6919 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackbornd6847842010-01-12 18:14:19 -08006920 if (finisher != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006921 mWaitingUpdate = true;
6922 }
6923 }
6924 }
6925 if (mWaitingUpdate) {
6926 return;
6927 }
6928 mDidUpdate = true;
6929 }
6930
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006931 mSystemReady = true;
6932 if (!mStartRunning) {
6933 return;
6934 }
6935 }
6936
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006937 ArrayList<ProcessRecord> procsToKill = null;
6938 synchronized(mPidsSelfLocked) {
6939 for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
6940 ProcessRecord proc = mPidsSelfLocked.valueAt(i);
6941 if (!isAllowedWhileBooting(proc.info)){
6942 if (procsToKill == null) {
6943 procsToKill = new ArrayList<ProcessRecord>();
6944 }
6945 procsToKill.add(proc);
6946 }
6947 }
6948 }
6949
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006950 synchronized(this) {
6951 if (procsToKill != null) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006952 for (int i=procsToKill.size()-1; i>=0; i--) {
6953 ProcessRecord proc = procsToKill.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08006954 Slog.i(TAG, "Removing system update proc: " + proc);
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08006955 removeProcessLocked(proc, true, false, "system update done");
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006956 }
6957 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07006958
6959 // Now that we have cleaned up any update processes, we
6960 // are ready to start launching real processes and know that
6961 // we won't trample on them any more.
6962 mProcessesReady = true;
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006963 }
6964
Joe Onorato8a9b2202010-02-26 18:56:32 -08006965 Slog.i(TAG, "System now ready");
Doug Zongker2bec3d42009-12-04 12:52:44 -08006966 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006967 SystemClock.uptimeMillis());
6968
6969 synchronized(this) {
Dianne Hackborn9acc0302009-08-25 00:27:12 -07006970 // Make sure we have no pre-ready processes sitting around.
6971
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006972 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
6973 ResolveInfo ri = mContext.getPackageManager()
6974 .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
Dianne Hackborn1655be42009-05-08 14:29:01 -07006975 STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006976 CharSequence errorMsg = null;
6977 if (ri != null) {
6978 ActivityInfo ai = ri.activityInfo;
6979 ApplicationInfo app = ai.applicationInfo;
6980 if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
6981 mTopAction = Intent.ACTION_FACTORY_TEST;
6982 mTopData = null;
6983 mTopComponent = new ComponentName(app.packageName,
6984 ai.name);
6985 } else {
6986 errorMsg = mContext.getResources().getText(
6987 com.android.internal.R.string.factorytest_not_system);
6988 }
6989 } else {
6990 errorMsg = mContext.getResources().getText(
6991 com.android.internal.R.string.factorytest_no_action);
6992 }
6993 if (errorMsg != null) {
6994 mTopAction = null;
6995 mTopData = null;
6996 mTopComponent = null;
6997 Message msg = Message.obtain();
6998 msg.what = SHOW_FACTORY_ERROR_MSG;
6999 msg.getData().putCharSequence("msg", errorMsg);
7000 mHandler.sendMessage(msg);
7001 }
7002 }
7003 }
7004
7005 retrieveSettings();
7006
Dianne Hackborna34f1ad2009-09-02 13:26:28 -07007007 if (goingCallback != null) goingCallback.run();
7008
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007009 synchronized (this) {
7010 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
7011 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007012 List apps = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -07007013 getPersistentApplications(STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007014 if (apps != null) {
7015 int N = apps.size();
7016 int i;
7017 for (i=0; i<N; i++) {
7018 ApplicationInfo info
7019 = (ApplicationInfo)apps.get(i);
7020 if (info != null &&
7021 !info.packageName.equals("android")) {
7022 addAppLocked(info);
7023 }
7024 }
7025 }
7026 } catch (RemoteException ex) {
7027 // pm is in same process, this will never happen.
7028 }
7029 }
7030
Dianne Hackborn9acc0302009-08-25 00:27:12 -07007031 // Start up initial activity.
7032 mBooting = true;
7033
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007034 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007035 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007036 Message msg = Message.obtain();
7037 msg.what = SHOW_UID_ERROR_MSG;
7038 mHandler.sendMessage(msg);
7039 }
7040 } catch (RemoteException e) {
7041 }
7042
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007043 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007044 }
7045 }
7046
Dan Egnorb7f03672009-12-09 16:22:32 -08007047 private boolean makeAppCrashingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08007048 String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007049 app.crashing = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08007050 app.crashingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08007051 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007052 startAppProblemLocked(app);
7053 app.stopFreezingAllLocked();
7054 return handleAppCrashLocked(app);
7055 }
7056
Dan Egnorb7f03672009-12-09 16:22:32 -08007057 private void makeAppNotRespondingLocked(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08007058 String activity, String shortMsg, String longMsg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007059 app.notResponding = true;
Dan Egnorb7f03672009-12-09 16:22:32 -08007060 app.notRespondingReport = generateProcessError(app,
Dan Egnor60d87622009-12-16 16:32:58 -08007061 ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
7062 activity, shortMsg, longMsg, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007063 startAppProblemLocked(app);
7064 app.stopFreezingAllLocked();
7065 }
7066
7067 /**
7068 * Generate a process error record, suitable for attachment to a ProcessRecord.
7069 *
7070 * @param app The ProcessRecord in which the error occurred.
7071 * @param condition Crashing, Application Not Responding, etc. Values are defined in
7072 * ActivityManager.AppErrorStateInfo
Dan Egnor60d87622009-12-16 16:32:58 -08007073 * @param activity The activity associated with the crash, if known.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007074 * @param shortMsg Short message describing the crash.
7075 * @param longMsg Long message describing the crash.
Dan Egnorb7f03672009-12-09 16:22:32 -08007076 * @param stackTrace Full crash stack trace, may be null.
7077 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007078 * @return Returns a fully-formed AppErrorStateInfo record.
7079 */
7080 private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
Dan Egnor60d87622009-12-16 16:32:58 -08007081 int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007082 ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
Dan Egnorb7f03672009-12-09 16:22:32 -08007083
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007084 report.condition = condition;
7085 report.processName = app.processName;
7086 report.pid = app.pid;
7087 report.uid = app.info.uid;
Dan Egnor60d87622009-12-16 16:32:58 -08007088 report.tag = activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007089 report.shortMsg = shortMsg;
7090 report.longMsg = longMsg;
Dan Egnorb7f03672009-12-09 16:22:32 -08007091 report.stackTrace = stackTrace;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007092
7093 return report;
7094 }
7095
Dan Egnor42471dd2010-01-07 17:25:22 -08007096 void killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007097 synchronized (this) {
7098 app.crashing = false;
7099 app.crashingReport = null;
7100 app.notResponding = false;
7101 app.notRespondingReport = null;
7102 if (app.anrDialog == fromDialog) {
7103 app.anrDialog = null;
7104 }
7105 if (app.waitDialog == fromDialog) {
7106 app.waitDialog = null;
7107 }
7108 if (app.pid > 0 && app.pid != MY_PID) {
Dan Egnor42471dd2010-01-07 17:25:22 -08007109 handleAppCrashLocked(app);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07007110 Slog.i(ActivityManagerService.TAG, "Killing " + app + ": user's request");
Dianne Hackborn8633e682010-04-22 16:03:41 -07007111 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
7112 app.processName, app.setAdj, "user's request after error");
Dianne Hackborn0c5001d2011-04-12 18:16:08 -07007113 Process.killProcessQuiet(app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007114 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007115 }
7116 }
Dan Egnor42471dd2010-01-07 17:25:22 -08007117
Dan Egnorb7f03672009-12-09 16:22:32 -08007118 private boolean handleAppCrashLocked(ProcessRecord app) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007119 long now = SystemClock.uptimeMillis();
7120
7121 Long crashTime = mProcessCrashTimes.get(app.info.processName,
7122 app.info.uid);
Dianne Hackborn7d608422011-08-07 16:24:18 -07007123 if (crashTime != null && now < crashTime+ProcessList.MIN_CRASH_INTERVAL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007124 // This process loses!
Joe Onorato8a9b2202010-02-26 18:56:32 -08007125 Slog.w(TAG, "Process " + app.info.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007126 + " has crashed too many times: killing!");
Doug Zongker2bec3d42009-12-04 12:52:44 -08007127 EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007128 app.info.processName, app.info.uid);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007129 for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
7130 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007131 if (r.app == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007132 Slog.w(TAG, " Force finishing activity "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007133 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007134 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007135 }
7136 }
7137 if (!app.persistent) {
7138 // We don't want to start this process again until the user
7139 // explicitly does so... but for persistent process, we really
7140 // need to keep it running. If a persistent process is actually
7141 // repeatedly crashing, then badness for everyone.
Doug Zongker2bec3d42009-12-04 12:52:44 -08007142 EventLog.writeEvent(EventLogTags.AM_PROC_BAD, app.info.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007143 app.info.processName);
7144 mBadProcesses.put(app.info.processName, app.info.uid, now);
7145 app.bad = true;
7146 mProcessCrashTimes.remove(app.info.processName, app.info.uid);
7147 app.removed = true;
Dianne Hackborn130b0d22011-07-26 22:07:48 -07007148 // Don't let services in this process be restarted and potentially
7149 // annoy the user repeatedly. Unless it is persistent, since those
7150 // processes run critical code.
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08007151 removeProcessLocked(app, false, false, "crash");
Dianne Hackborncb44d962011-03-10 17:02:27 -08007152 mMainStack.resumeTopActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007153 return false;
7154 }
Dianne Hackborncb44d962011-03-10 17:02:27 -08007155 mMainStack.resumeTopActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07007156 } else {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007157 ActivityRecord r = mMainStack.topRunningActivityLocked(null);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07007158 if (r.app == app) {
7159 // If the top running activity is from this crashing
7160 // process, then terminate it to avoid getting in a loop.
7161 Slog.w(TAG, " Force finishing activity "
7162 + r.intent.getComponent().flattenToShortString());
Dianne Hackbornbe707852011-11-11 14:32:10 -08007163 int index = mMainStack.indexOfActivityLocked(r);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007164 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07007165 Activity.RESULT_CANCELED, null, "crashed");
Dianne Hackborn070783f2010-12-29 16:46:28 -08007166 // Also terminate any activities below it that aren't yet
Dianne Hackbornf83c5552010-03-31 22:19:32 -07007167 // stopped, to avoid a situation where one will get
7168 // re-start our crashing activity once it gets resumed again.
7169 index--;
7170 if (index >= 0) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007171 r = (ActivityRecord)mMainStack.mHistory.get(index);
Dianne Hackbornf83c5552010-03-31 22:19:32 -07007172 if (r.state == ActivityState.RESUMED
7173 || r.state == ActivityState.PAUSING
7174 || r.state == ActivityState.PAUSED) {
Dianne Hackborn94cb2eb2011-01-13 21:09:44 -08007175 if (!r.isHomeActivity || mHomeProcess != r.app) {
Dianne Hackbornf83c5552010-03-31 22:19:32 -07007176 Slog.w(TAG, " Force finishing activity "
7177 + r.intent.getComponent().flattenToShortString());
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07007178 r.stack.finishActivityLocked(r, index,
Dianne Hackbornf83c5552010-03-31 22:19:32 -07007179 Activity.RESULT_CANCELED, null, "crashed");
7180 }
7181 }
7182 }
7183 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007184 }
7185
7186 // Bump up the crash count of any services currently running in the proc.
7187 if (app.services.size() != 0) {
7188 // Any services running in the application need to be placed
7189 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -07007190 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007191 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07007192 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007193 sr.crashCount++;
7194 }
7195 }
Mattias Larssona4fd0072010-06-22 22:37:03 +02007196
7197 // If the crashing process is what we consider to be the "home process" and it has been
7198 // replaced by a third-party app, clear the package preferred activities from packages
7199 // with a home activity running in the process to prevent a repeatedly crashing app
7200 // from blocking the user to manually clear the list.
7201 if (app == mHomeProcess && mHomeProcess.activities.size() > 0
7202 && (mHomeProcess.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
7203 Iterator it = mHomeProcess.activities.iterator();
7204 while (it.hasNext()) {
Jean-Baptiste Queru5ea89f72010-07-30 09:30:31 -07007205 ActivityRecord r = (ActivityRecord)it.next();
Mattias Larssona4fd0072010-06-22 22:37:03 +02007206 if (r.isHomeActivity) {
7207 Log.i(TAG, "Clearing package preferred activities from " + r.packageName);
7208 try {
7209 ActivityThread.getPackageManager()
7210 .clearPackagePreferredActivities(r.packageName);
7211 } catch (RemoteException c) {
7212 // pm is in same process, this will never happen.
7213 }
7214 }
7215 }
7216 }
7217
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007218 mProcessCrashTimes.put(app.info.processName, app.info.uid, now);
7219 return true;
7220 }
7221
7222 void startAppProblemLocked(ProcessRecord app) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08007223 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
7224 mContext, app.info.packageName, app.info.flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007225 skipCurrentReceiverLocked(app);
7226 }
7227
7228 void skipCurrentReceiverLocked(ProcessRecord app) {
7229 boolean reschedule = false;
7230 BroadcastRecord r = app.curReceiver;
7231 if (r != null) {
7232 // The current broadcast is waiting for this app's receiver
7233 // to be finished. Looks like that's not going to happen, so
7234 // let the broadcast continue.
Jeff Brown4d94a762010-09-23 11:33:28 -07007235 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007236 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
7237 r.resultExtras, r.resultAbort, true);
7238 reschedule = true;
7239 }
7240 r = mPendingBroadcast;
7241 if (r != null && r.curApp == app) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007242 if (DEBUG_BROADCAST) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007243 "skip & discard pending app " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -07007244 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007245 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
7246 r.resultExtras, r.resultAbort, true);
7247 reschedule = true;
7248 }
7249 if (reschedule) {
7250 scheduleBroadcastsLocked();
7251 }
7252 }
7253
Dan Egnor60d87622009-12-16 16:32:58 -08007254 /**
7255 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
7256 * The application process will exit immediately after this call returns.
7257 * @param app object of the crashing app, null for the system server
7258 * @param crashInfo describing the exception
7259 */
7260 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
Dianne Hackborncb44d962011-03-10 17:02:27 -08007261 ProcessRecord r = findAppProcess(app, "Crash");
Jeff Sharkeya353d262011-10-28 11:12:06 -07007262 final String processName = app == null ? "system_server"
7263 : (r == null ? "unknown" : r.processName);
Dan Egnor60d87622009-12-16 16:32:58 -08007264
7265 EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
Jeff Sharkeya353d262011-10-28 11:12:06 -07007266 processName,
Dan Egnor2780e732010-01-22 14:47:35 -08007267 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08007268 crashInfo.exceptionClassName,
7269 crashInfo.exceptionMessage,
7270 crashInfo.throwFileName,
7271 crashInfo.throwLineNumber);
7272
Jeff Sharkeya353d262011-10-28 11:12:06 -07007273 addErrorToDropBox("crash", r, processName, null, null, null, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08007274
7275 crashApplication(r, crashInfo);
7276 }
7277
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07007278 public void handleApplicationStrictModeViolation(
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007279 IBinder app,
7280 int violationMask,
7281 StrictMode.ViolationInfo info) {
Dianne Hackborncb44d962011-03-10 17:02:27 -08007282 ProcessRecord r = findAppProcess(app, "StrictMode");
7283 if (r == null) {
7284 return;
7285 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07007286
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07007287 if ((violationMask & StrictMode.PENALTY_DROPBOX) != 0) {
Brad Fitzpatrickf3d86be2010-11-23 10:31:52 -08007288 Integer stackFingerprint = info.hashCode();
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07007289 boolean logIt = true;
7290 synchronized (mAlreadyLoggedViolatedStacks) {
7291 if (mAlreadyLoggedViolatedStacks.contains(stackFingerprint)) {
7292 logIt = false;
7293 // TODO: sub-sample into EventLog for these, with
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007294 // the info.durationMillis? Then we'd get
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07007295 // the relative pain numbers, without logging all
7296 // the stack traces repeatedly. We'd want to do
7297 // likewise in the client code, which also does
7298 // dup suppression, before the Binder call.
7299 } else {
7300 if (mAlreadyLoggedViolatedStacks.size() >= MAX_DUP_SUPPRESSED_STACKS) {
7301 mAlreadyLoggedViolatedStacks.clear();
7302 }
7303 mAlreadyLoggedViolatedStacks.add(stackFingerprint);
7304 }
7305 }
7306 if (logIt) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007307 logStrictModeViolationToDropBox(r, info);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07007308 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07007309 }
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07007310
7311 if ((violationMask & StrictMode.PENALTY_DIALOG) != 0) {
7312 AppErrorResult result = new AppErrorResult();
7313 synchronized (this) {
7314 final long origId = Binder.clearCallingIdentity();
7315
7316 Message msg = Message.obtain();
7317 msg.what = SHOW_STRICT_MODE_VIOLATION_MSG;
7318 HashMap<String, Object> data = new HashMap<String, Object>();
7319 data.put("result", result);
7320 data.put("app", r);
Brad Fitzpatrick143666f2010-06-14 12:40:21 -07007321 data.put("violationMask", violationMask);
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007322 data.put("info", info);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07007323 msg.obj = data;
7324 mHandler.sendMessage(msg);
7325
7326 Binder.restoreCallingIdentity(origId);
7327 }
7328 int res = result.get();
Dianne Hackbornb424b632010-08-18 15:59:05 -07007329 Slog.w(TAG, "handleApplicationStrictModeViolation; res=" + res);
Brad Fitzpatrick46d42382010-06-11 13:57:58 -07007330 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07007331 }
7332
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007333 // Depending on the policy in effect, there could be a bunch of
7334 // these in quick succession so we try to batch these together to
7335 // minimize disk writes, number of dropbox entries, and maximize
7336 // compression, by having more fewer, larger records.
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007337 private void logStrictModeViolationToDropBox(
7338 ProcessRecord process,
7339 StrictMode.ViolationInfo info) {
7340 if (info == null) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007341 return;
7342 }
7343 final boolean isSystemApp = process == null ||
7344 (process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
7345 ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
Jeff Sharkeya353d262011-10-28 11:12:06 -07007346 final String processName = process == null ? "unknown" : process.processName;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007347 final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
7348 final DropBoxManager dbox = (DropBoxManager)
7349 mContext.getSystemService(Context.DROPBOX_SERVICE);
7350
7351 // Exit early if the dropbox isn't configured to accept this report type.
7352 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
7353
7354 boolean bufferWasEmpty;
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007355 boolean needsFlush;
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007356 final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
7357 synchronized (sb) {
7358 bufferWasEmpty = sb.length() == 0;
Jeff Sharkeya353d262011-10-28 11:12:06 -07007359 appendDropBoxProcessHeaders(process, processName, sb);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007360 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
7361 sb.append("System-App: ").append(isSystemApp).append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007362 sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
7363 if (info.violationNumThisLoop != 0) {
7364 sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
7365 }
Brad Fitzpatrick599ca292010-10-22 14:47:03 -07007366 if (info.numAnimationsRunning != 0) {
7367 sb.append("Animations-Running: ").append(info.numAnimationsRunning).append("\n");
7368 }
Brad Fitzpatrickbfb19192010-10-29 15:25:44 -07007369 if (info.broadcastIntentAction != null) {
7370 sb.append("Broadcast-Intent-Action: ").append(info.broadcastIntentAction).append("\n");
7371 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08007372 if (info.durationMillis != -1) {
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007373 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007374 }
Brad Fitzpatrickbfbe5772011-01-19 00:10:58 -08007375 if (info.numInstances != -1) {
7376 sb.append("Instance-Count: ").append(info.numInstances).append("\n");
7377 }
Brad Fitzpatricke7520d82010-11-10 18:08:36 -08007378 if (info.tags != null) {
7379 for (String tag : info.tags) {
7380 sb.append("Span-Tag: ").append(tag).append("\n");
7381 }
7382 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007383 sb.append("\n");
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -07007384 if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
7385 sb.append(info.crashInfo.stackTrace);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007386 }
7387 sb.append("\n");
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007388
7389 // Only buffer up to ~64k. Various logging bits truncate
7390 // things at 128k.
7391 needsFlush = (sb.length() > 64 * 1024);
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007392 }
7393
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007394 // Flush immediately if the buffer's grown too large, or this
7395 // is a non-system app. Non-system apps are isolated with a
7396 // different tag & policy and not batched.
7397 //
7398 // Batching is useful during internal testing with
7399 // StrictMode settings turned up high. Without batching,
7400 // thousands of separate files could be created on boot.
7401 if (!isSystemApp || needsFlush) {
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007402 new Thread("Error dump: " + dropboxTag) {
7403 @Override
7404 public void run() {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007405 String report;
7406 synchronized (sb) {
7407 report = sb.toString();
7408 sb.delete(0, sb.length());
7409 sb.trimToSize();
7410 }
7411 if (report.length() != 0) {
7412 dbox.addText(dropboxTag, report);
7413 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007414 }
7415 }.start();
7416 return;
7417 }
7418
7419 // System app batching:
7420 if (!bufferWasEmpty) {
Brad Fitzpatricke73eb532010-07-27 16:54:39 -07007421 // An existing dropbox-writing thread is outstanding, so
7422 // we don't need to start it up. The existing thread will
7423 // catch the buffer appends we just did.
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007424 return;
7425 }
7426
7427 // Worker thread to both batch writes and to avoid blocking the caller on I/O.
7428 // (After this point, we shouldn't access AMS internal data structures.)
7429 new Thread("Error dump: " + dropboxTag) {
7430 @Override
7431 public void run() {
7432 // 5 second sleep to let stacks arrive and be batched together
7433 try {
7434 Thread.sleep(5000); // 5 seconds
7435 } catch (InterruptedException e) {}
7436
7437 String errorReport;
7438 synchronized (mStrictModeBuffer) {
7439 errorReport = mStrictModeBuffer.toString();
7440 if (errorReport.length() == 0) {
7441 return;
7442 }
7443 mStrictModeBuffer.delete(0, mStrictModeBuffer.length());
7444 mStrictModeBuffer.trimToSize();
7445 }
7446 dbox.addText(dropboxTag, errorReport);
7447 }
7448 }.start();
7449 }
7450
Dan Egnor60d87622009-12-16 16:32:58 -08007451 /**
7452 * Used by {@link Log} via {@link com.android.internal.os.RuntimeInit} to report serious errors.
7453 * @param app object of the crashing app, null for the system server
7454 * @param tag reported by the caller
7455 * @param crashInfo describing the context of the error
7456 * @return true if the process should exit immediately (WTF is fatal)
7457 */
7458 public boolean handleApplicationWtf(IBinder app, String tag,
Dan Egnorb7f03672009-12-09 16:22:32 -08007459 ApplicationErrorReport.CrashInfo crashInfo) {
Dianne Hackborncb44d962011-03-10 17:02:27 -08007460 ProcessRecord r = findAppProcess(app, "WTF");
Jeff Sharkeya353d262011-10-28 11:12:06 -07007461 final String processName = app == null ? "system_server"
7462 : (r == null ? "unknown" : r.processName);
Dan Egnor60d87622009-12-16 16:32:58 -08007463
7464 EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
Jeff Sharkeya353d262011-10-28 11:12:06 -07007465 processName,
Dan Egnor2780e732010-01-22 14:47:35 -08007466 r == null ? -1 : r.info.flags,
Dan Egnor60d87622009-12-16 16:32:58 -08007467 tag, crashInfo.exceptionMessage);
7468
Jeff Sharkeya353d262011-10-28 11:12:06 -07007469 addErrorToDropBox("wtf", r, processName, null, null, tag, null, null, crashInfo);
Dan Egnor60d87622009-12-16 16:32:58 -08007470
Dianne Hackborn1ab43772011-03-15 14:38:02 -07007471 if (r != null && r.pid != Process.myPid() &&
7472 Settings.Secure.getInt(mContext.getContentResolver(),
7473 Settings.Secure.WTF_IS_FATAL, 0) != 0) {
Dan Egnor60d87622009-12-16 16:32:58 -08007474 crashApplication(r, crashInfo);
7475 return true;
7476 } else {
7477 return false;
7478 }
7479 }
7480
7481 /**
7482 * @param app object of some object (as stored in {@link com.android.internal.os.RuntimeInit})
7483 * @return the corresponding {@link ProcessRecord} object, or null if none could be found
7484 */
Dianne Hackborncb44d962011-03-10 17:02:27 -08007485 private ProcessRecord findAppProcess(IBinder app, String reason) {
Dan Egnor60d87622009-12-16 16:32:58 -08007486 if (app == null) {
7487 return null;
7488 }
7489
7490 synchronized (this) {
7491 for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
7492 final int NA = apps.size();
7493 for (int ia=0; ia<NA; ia++) {
7494 ProcessRecord p = apps.valueAt(ia);
7495 if (p.thread != null && p.thread.asBinder() == app) {
7496 return p;
7497 }
7498 }
7499 }
7500
Dianne Hackborncb44d962011-03-10 17:02:27 -08007501 Slog.w(TAG, "Can't find mystery application for " + reason
7502 + " from pid=" + Binder.getCallingPid()
7503 + " uid=" + Binder.getCallingUid() + ": " + app);
Dan Egnor60d87622009-12-16 16:32:58 -08007504 return null;
7505 }
7506 }
7507
7508 /**
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007509 * Utility function for addErrorToDropBox and handleStrictModeViolation's logging
7510 * to append various headers to the dropbox log text.
Dan Egnor60d87622009-12-16 16:32:58 -08007511 */
Jeff Sharkeya353d262011-10-28 11:12:06 -07007512 private void appendDropBoxProcessHeaders(ProcessRecord process, String processName,
7513 StringBuilder sb) {
Vairavan Srinivasan68a4e0a2011-02-14 20:45:59 -08007514 // Watchdog thread ends up invoking this function (with
7515 // a null ProcessRecord) to add the stack file to dropbox.
7516 // Do not acquire a lock on this (am) in such cases, as it
7517 // could cause a potential deadlock, if and when watchdog
7518 // is invoked due to unavailability of lock on am and it
7519 // would prevent watchdog from killing system_server.
7520 if (process == null) {
Jeff Sharkeya353d262011-10-28 11:12:06 -07007521 sb.append("Process: ").append(processName).append("\n");
Vairavan Srinivasan68a4e0a2011-02-14 20:45:59 -08007522 return;
7523 }
Brad Fitzpatrick1e02d362010-09-10 09:19:50 -07007524 // Note: ProcessRecord 'process' is guarded by the service
7525 // instance. (notably process.pkgList, which could otherwise change
7526 // concurrently during execution of this method)
7527 synchronized (this) {
Jeff Sharkeya353d262011-10-28 11:12:06 -07007528 sb.append("Process: ").append(processName).append("\n");
Dan Egnora455d192010-03-12 08:52:28 -08007529 int flags = process.info.flags;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007530 IPackageManager pm = AppGlobals.getPackageManager();
Dan Egnora455d192010-03-12 08:52:28 -08007531 sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
7532 for (String pkg : process.pkgList) {
7533 sb.append("Package: ").append(pkg);
Dan Egnor42471dd2010-01-07 17:25:22 -08007534 try {
Dan Egnora455d192010-03-12 08:52:28 -08007535 PackageInfo pi = pm.getPackageInfo(pkg, 0);
7536 if (pi != null) {
7537 sb.append(" v").append(pi.versionCode);
7538 if (pi.versionName != null) {
7539 sb.append(" (").append(pi.versionName).append(")");
7540 }
7541 }
7542 } catch (RemoteException e) {
7543 Slog.e(TAG, "Error getting package info: " + pkg, e);
Dan Egnor60d87622009-12-16 16:32:58 -08007544 }
Dan Egnora455d192010-03-12 08:52:28 -08007545 sb.append("\n");
Dan Egnor60d87622009-12-16 16:32:58 -08007546 }
Dan Egnora455d192010-03-12 08:52:28 -08007547 }
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007548 }
7549
7550 private static String processClass(ProcessRecord process) {
7551 if (process == null || process.pid == MY_PID) {
7552 return "system_server";
7553 } else if ((process.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
7554 return "system_app";
7555 } else {
7556 return "data_app";
7557 }
7558 }
7559
7560 /**
7561 * Write a description of an error (crash, WTF, ANR) to the drop box.
7562 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
7563 * @param process which caused the error, null means the system server
7564 * @param activity which triggered the error, null if unknown
7565 * @param parent activity related to the error, null if unknown
7566 * @param subject line related to the error, null if absent
7567 * @param report in long form describing the error, null if absent
7568 * @param logFile to include in the report, null if none
7569 * @param crashInfo giving an application stack trace, null if absent
7570 */
7571 public void addErrorToDropBox(String eventType,
Jeff Sharkeya353d262011-10-28 11:12:06 -07007572 ProcessRecord process, String processName, ActivityRecord activity,
7573 ActivityRecord parent, String subject,
Brad Fitzpatrickad13b982010-07-14 12:35:53 -07007574 final String report, final File logFile,
7575 final ApplicationErrorReport.CrashInfo crashInfo) {
7576 // NOTE -- this must never acquire the ActivityManagerService lock,
7577 // otherwise the watchdog may be prevented from resetting the system.
7578
7579 final String dropboxTag = processClass(process) + "_" + eventType;
7580 final DropBoxManager dbox = (DropBoxManager)
7581 mContext.getSystemService(Context.DROPBOX_SERVICE);
7582
7583 // Exit early if the dropbox isn't configured to accept this report type.
7584 if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
7585
7586 final StringBuilder sb = new StringBuilder(1024);
Jeff Sharkeya353d262011-10-28 11:12:06 -07007587 appendDropBoxProcessHeaders(process, processName, sb);
Dan Egnora455d192010-03-12 08:52:28 -08007588 if (activity != null) {
7589 sb.append("Activity: ").append(activity.shortComponentName).append("\n");
7590 }
7591 if (parent != null && parent.app != null && parent.app.pid != process.pid) {
7592 sb.append("Parent-Process: ").append(parent.app.processName).append("\n");
7593 }
7594 if (parent != null && parent != activity) {
7595 sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
7596 }
7597 if (subject != null) {
7598 sb.append("Subject: ").append(subject).append("\n");
7599 }
7600 sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
Christian Lindeberg03d2ca62010-09-28 14:52:20 +02007601 if (Debug.isDebuggerConnected()) {
7602 sb.append("Debugger: Connected\n");
7603 }
Dan Egnora455d192010-03-12 08:52:28 -08007604 sb.append("\n");
7605
7606 // Do the rest in a worker thread to avoid blocking the caller on I/O
7607 // (After this point, we shouldn't access AMS internal data structures.)
7608 Thread worker = new Thread("Error dump: " + dropboxTag) {
7609 @Override
7610 public void run() {
7611 if (report != null) {
7612 sb.append(report);
7613 }
7614 if (logFile != null) {
7615 try {
7616 sb.append(FileUtils.readTextFile(logFile, 128 * 1024, "\n\n[[TRUNCATED]]"));
7617 } catch (IOException e) {
7618 Slog.e(TAG, "Error reading " + logFile, e);
7619 }
7620 }
7621 if (crashInfo != null && crashInfo.stackTrace != null) {
7622 sb.append(crashInfo.stackTrace);
7623 }
7624
7625 String setting = Settings.Secure.ERROR_LOGCAT_PREFIX + dropboxTag;
7626 int lines = Settings.Secure.getInt(mContext.getContentResolver(), setting, 0);
7627 if (lines > 0) {
7628 sb.append("\n");
7629
7630 // Merge several logcat streams, and take the last N lines
7631 InputStreamReader input = null;
7632 try {
7633 java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat",
7634 "-v", "time", "-b", "events", "-b", "system", "-b", "main",
7635 "-t", String.valueOf(lines)).redirectErrorStream(true).start();
7636
7637 try { logcat.getOutputStream().close(); } catch (IOException e) {}
7638 try { logcat.getErrorStream().close(); } catch (IOException e) {}
7639 input = new InputStreamReader(logcat.getInputStream());
7640
7641 int num;
7642 char[] buf = new char[8192];
7643 while ((num = input.read(buf)) > 0) sb.append(buf, 0, num);
7644 } catch (IOException e) {
7645 Slog.e(TAG, "Error running logcat", e);
7646 } finally {
7647 if (input != null) try { input.close(); } catch (IOException e) {}
7648 }
7649 }
7650
7651 dbox.addText(dropboxTag, sb.toString());
Dan Egnor60d87622009-12-16 16:32:58 -08007652 }
Dan Egnora455d192010-03-12 08:52:28 -08007653 };
7654
7655 if (process == null || process.pid == MY_PID) {
7656 worker.run(); // We may be about to die -- need to run this synchronously
7657 } else {
7658 worker.start();
Dan Egnor60d87622009-12-16 16:32:58 -08007659 }
7660 }
7661
7662 /**
7663 * Bring up the "unexpected error" dialog box for a crashing app.
7664 * Deal with edge cases (intercepts from instrumented applications,
7665 * ActivityController, error intent receivers, that sort of thing).
7666 * @param r the application crashing
7667 * @param crashInfo describing the failure
7668 */
7669 private void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007670 long timeMillis = System.currentTimeMillis();
7671 String shortMsg = crashInfo.exceptionClassName;
7672 String longMsg = crashInfo.exceptionMessage;
7673 String stackTrace = crashInfo.stackTrace;
7674 if (shortMsg != null && longMsg != null) {
7675 longMsg = shortMsg + ": " + longMsg;
7676 } else if (shortMsg != null) {
7677 longMsg = shortMsg;
7678 }
7679
Dan Egnor60d87622009-12-16 16:32:58 -08007680 AppErrorResult result = new AppErrorResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007681 synchronized (this) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007682 if (mController != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007683 try {
7684 String name = r != null ? r.processName : null;
7685 int pid = r != null ? r.pid : Binder.getCallingPid();
Dan Egnor60d87622009-12-16 16:32:58 -08007686 if (!mController.appCrashed(name, pid,
Dan Egnorb7f03672009-12-09 16:22:32 -08007687 shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007688 Slog.w(TAG, "Force-killing crashed app " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007689 + " at watcher's request");
7690 Process.killProcess(pid);
Dan Egnorb7f03672009-12-09 16:22:32 -08007691 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007692 }
7693 } catch (RemoteException e) {
Dianne Hackbornb06ea702009-07-13 13:07:51 -07007694 mController = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007695 }
7696 }
7697
7698 final long origId = Binder.clearCallingIdentity();
7699
7700 // If this process is running instrumentation, finish it.
7701 if (r != null && r.instrumentationClass != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007702 Slog.w(TAG, "Error in app " + r.processName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007703 + " running instrumentation " + r.instrumentationClass + ":");
Joe Onorato8a9b2202010-02-26 18:56:32 -08007704 if (shortMsg != null) Slog.w(TAG, " " + shortMsg);
7705 if (longMsg != null) Slog.w(TAG, " " + longMsg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007706 Bundle info = new Bundle();
7707 info.putString("shortMsg", shortMsg);
7708 info.putString("longMsg", longMsg);
7709 finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
7710 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007711 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007712 }
7713
Dan Egnor60d87622009-12-16 16:32:58 -08007714 // If we can't identify the process or it's already exceeded its crash quota,
7715 // quit right away without showing a crash dialog.
7716 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007717 Binder.restoreCallingIdentity(origId);
Dan Egnorb7f03672009-12-09 16:22:32 -08007718 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007719 }
7720
7721 Message msg = Message.obtain();
7722 msg.what = SHOW_ERROR_MSG;
7723 HashMap data = new HashMap();
7724 data.put("result", result);
7725 data.put("app", r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007726 msg.obj = data;
7727 mHandler.sendMessage(msg);
7728
7729 Binder.restoreCallingIdentity(origId);
7730 }
7731
7732 int res = result.get();
7733
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007734 Intent appErrorIntent = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007735 synchronized (this) {
7736 if (r != null) {
7737 mProcessCrashTimes.put(r.info.processName, r.info.uid,
7738 SystemClock.uptimeMillis());
7739 }
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007740 if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
Dan Egnorb7f03672009-12-09 16:22:32 -08007741 appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007742 }
7743 }
7744
7745 if (appErrorIntent != null) {
7746 try {
7747 mContext.startActivity(appErrorIntent);
7748 } catch (ActivityNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007749 Slog.w(TAG, "bug report receiver dissappeared", e);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007750 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007751 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007752 }
Dan Egnorb7f03672009-12-09 16:22:32 -08007753
7754 Intent createAppErrorIntentLocked(ProcessRecord r,
7755 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
7756 ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007757 if (report == null) {
7758 return null;
7759 }
7760 Intent result = new Intent(Intent.ACTION_APP_ERROR);
7761 result.setComponent(r.errorReportReceiver);
7762 result.putExtra(Intent.EXTRA_BUG_REPORT, report);
7763 result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
7764 return result;
7765 }
7766
Dan Egnorb7f03672009-12-09 16:22:32 -08007767 private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
7768 long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007769 if (r.errorReportReceiver == null) {
7770 return null;
7771 }
7772
7773 if (!r.crashing && !r.notResponding) {
7774 return null;
7775 }
7776
Dan Egnorb7f03672009-12-09 16:22:32 -08007777 ApplicationErrorReport report = new ApplicationErrorReport();
7778 report.packageName = r.info.packageName;
7779 report.installerPackageName = r.errorReportReceiver.getPackageName();
7780 report.processName = r.processName;
7781 report.time = timeMillis;
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +01007782 report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007783
Dan Egnorb7f03672009-12-09 16:22:32 -08007784 if (r.crashing) {
7785 report.type = ApplicationErrorReport.TYPE_CRASH;
7786 report.crashInfo = crashInfo;
7787 } else if (r.notResponding) {
7788 report.type = ApplicationErrorReport.TYPE_ANR;
7789 report.anrInfo = new ApplicationErrorReport.AnrInfo();
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007790
Dan Egnorb7f03672009-12-09 16:22:32 -08007791 report.anrInfo.activity = r.notRespondingReport.tag;
7792 report.anrInfo.cause = r.notRespondingReport.shortMsg;
7793 report.anrInfo.info = r.notRespondingReport.longMsg;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007794 }
7795
Dan Egnorb7f03672009-12-09 16:22:32 -08007796 return report;
Jacek Surazskif5b9c722009-05-18 12:09:59 +02007797 }
7798
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007799 public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
7800 // assume our apps are happy - lazy create the list
7801 List<ActivityManager.ProcessErrorStateInfo> errList = null;
7802
7803 synchronized (this) {
7804
7805 // iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007806 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7807 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007808 if ((app.thread != null) && (app.crashing || app.notResponding)) {
7809 // This one's in trouble, so we'll generate a report for it
7810 // crashes are higher priority (in case there's a crash *and* an anr)
7811 ActivityManager.ProcessErrorStateInfo report = null;
7812 if (app.crashing) {
7813 report = app.crashingReport;
7814 } else if (app.notResponding) {
7815 report = app.notRespondingReport;
7816 }
7817
7818 if (report != null) {
7819 if (errList == null) {
7820 errList = new ArrayList<ActivityManager.ProcessErrorStateInfo>(1);
7821 }
7822 errList.add(report);
7823 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007824 Slog.w(TAG, "Missing app error report, app = " + app.processName +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007825 " crashing = " + app.crashing +
7826 " notResponding = " + app.notResponding);
7827 }
7828 }
7829 }
7830 }
7831
7832 return errList;
7833 }
Dianne Hackborn905577f2011-09-07 18:31:28 -07007834
7835 static int oomAdjToImportance(int adj, ActivityManager.RunningAppProcessInfo currApp) {
Dianne Hackborne02c88a2011-10-28 13:58:15 -07007836 if (adj >= ProcessList.HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn905577f2011-09-07 18:31:28 -07007837 if (currApp != null) {
7838 currApp.lru = adj - ProcessList.HIDDEN_APP_MIN_ADJ + 1;
7839 }
7840 return ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
Dianne Hackborne02c88a2011-10-28 13:58:15 -07007841 } else if (adj >= ProcessList.SERVICE_B_ADJ) {
7842 return ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
Dianne Hackborn905577f2011-09-07 18:31:28 -07007843 } else if (adj >= ProcessList.HOME_APP_ADJ) {
7844 if (currApp != null) {
7845 currApp.lru = 0;
7846 }
7847 return ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
Dianne Hackborne02c88a2011-10-28 13:58:15 -07007848 } else if (adj >= ProcessList.SERVICE_ADJ) {
Dianne Hackborn905577f2011-09-07 18:31:28 -07007849 return ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
7850 } else if (adj >= ProcessList.HEAVY_WEIGHT_APP_ADJ) {
7851 return ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE;
7852 } else if (adj >= ProcessList.PERCEPTIBLE_APP_ADJ) {
7853 return ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
7854 } else if (adj >= ProcessList.VISIBLE_APP_ADJ) {
7855 return ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
7856 } else {
7857 return ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
7858 }
7859 }
7860
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007861 public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
7862 // Lazy instantiation of list
7863 List<ActivityManager.RunningAppProcessInfo> runList = null;
7864 synchronized (this) {
7865 // Iterate across all processes
Dianne Hackborndd71fc82009-12-16 19:24:32 -08007866 for (int i=mLruProcesses.size()-1; i>=0; i--) {
7867 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007868 if ((app.thread != null) && (!app.crashing && !app.notResponding)) {
7869 // Generate process state info for running application
7870 ActivityManager.RunningAppProcessInfo currApp =
7871 new ActivityManager.RunningAppProcessInfo(app.processName,
7872 app.pid, app.getPackageList());
Dianne Hackborneb034652009-09-07 00:49:58 -07007873 currApp.uid = app.info.uid;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007874 if (mHeavyWeightProcess == app) {
Dianne Hackborn482566e2010-09-03 12:51:28 -07007875 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
Dianne Hackbornbaf42c62010-06-24 11:23:39 -07007876 }
Dianne Hackborn42499172010-10-15 18:45:07 -07007877 if (app.persistent) {
7878 currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_PERSISTENT;
7879 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007880 int adj = app.curAdj;
Dianne Hackborn905577f2011-09-07 18:31:28 -07007881 currApp.importance = oomAdjToImportance(adj, currApp);
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007882 currApp.importanceReasonCode = app.adjTypeCode;
7883 if (app.adjSource instanceof ProcessRecord) {
7884 currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
Dianne Hackborn905577f2011-09-07 18:31:28 -07007885 currApp.importanceReasonImportance = oomAdjToImportance(
7886 app.adjSourceOom, null);
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007887 } else if (app.adjSource instanceof ActivityRecord) {
7888 ActivityRecord r = (ActivityRecord)app.adjSource;
Dianne Hackborndd9b82c2009-09-03 00:18:47 -07007889 if (r.app != null) currApp.importanceReasonPid = r.app.pid;
7890 }
7891 if (app.adjTarget instanceof ComponentName) {
7892 currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
7893 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007894 //Slog.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007895 // + " lru=" + currApp.lru);
7896 if (runList == null) {
7897 runList = new ArrayList<ActivityManager.RunningAppProcessInfo>();
7898 }
7899 runList.add(currApp);
7900 }
7901 }
7902 }
7903 return runList;
7904 }
7905
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007906 public List<ApplicationInfo> getRunningExternalApplications() {
7907 List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
7908 List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
7909 if (runningApps != null && runningApps.size() > 0) {
7910 Set<String> extList = new HashSet<String>();
7911 for (ActivityManager.RunningAppProcessInfo app : runningApps) {
7912 if (app.pkgList != null) {
7913 for (String pkg : app.pkgList) {
7914 extList.add(pkg);
7915 }
7916 }
7917 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07007918 IPackageManager pm = AppGlobals.getPackageManager();
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007919 for (String pkg : extList) {
7920 try {
7921 ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
7922 if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
7923 retList.add(info);
7924 }
7925 } catch (RemoteException e) {
7926 }
7927 }
7928 }
7929 return retList;
7930 }
7931
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007932 @Override
7933 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007934 if (checkCallingPermission(android.Manifest.permission.DUMP)
7935 != PackageManager.PERMISSION_GRANTED) {
7936 pw.println("Permission Denial: can't dump ActivityManager from from pid="
7937 + Binder.getCallingPid()
7938 + ", uid=" + Binder.getCallingUid()
7939 + " without permission "
7940 + android.Manifest.permission.DUMP);
7941 return;
7942 }
7943
7944 boolean dumpAll = false;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007945 boolean dumpClient = false;
Dianne Hackbornee9aef02011-11-16 13:21:46 -08007946 String dumpPackage = null;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007947
7948 int opti = 0;
7949 while (opti < args.length) {
7950 String opt = args[opti];
7951 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
7952 break;
7953 }
7954 opti++;
7955 if ("-a".equals(opt)) {
7956 dumpAll = true;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007957 } else if ("-c".equals(opt)) {
7958 dumpClient = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007959 } else if ("-h".equals(opt)) {
7960 pw.println("Activity manager dump options:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007961 pw.println(" [-a] [-c] [-h] [cmd] ...");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007962 pw.println(" cmd may be one of:");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007963 pw.println(" a[ctivities]: activity stack state");
Dianne Hackbornee9aef02011-11-16 13:21:46 -08007964 pw.println(" b[roadcasts] [PACKAGE_NAME]: broadcast state");
7965 pw.println(" i[ntents] [PACKAGE_NAME]: pending intent state");
7966 pw.println(" p[rocesses] [PACKAGE_NAME]: process state");
Dianne Hackborn287952c2010-09-22 22:34:31 -07007967 pw.println(" o[om]: out of memory management");
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07007968 pw.println(" prov[iders] [COMP_SPEC ...]: content provider state");
Marco Nelissen18cb2872011-11-15 11:19:53 -08007969 pw.println(" provider [COMP_SPEC]: provider client-side state");
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07007970 pw.println(" s[ervices] [COMP_SPEC ...]: service state");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007971 pw.println(" service [COMP_SPEC]: service client-side state");
Dianne Hackbornee9aef02011-11-16 13:21:46 -08007972 pw.println(" package [PACKAGE_NAME]: all state related to given package");
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07007973 pw.println(" all: dump all activities");
7974 pw.println(" top: dump the top activity");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007975 pw.println(" cmd may also be a COMP_SPEC to dump activities.");
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07007976 pw.println(" COMP_SPEC may be a component name (com.foo/.myApp),");
7977 pw.println(" a partial substring in a component name, a");
7978 pw.println(" hex object identifier.");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07007979 pw.println(" -a: include all available server state.");
7980 pw.println(" -c: include client state.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007981 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007982 } else {
7983 pw.println("Unknown argument: " + opt + "; use -h for help");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007984 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007985 }
7986
7987 // Is the caller requesting to dump a particular piece of data?
7988 if (opti < args.length) {
7989 String cmd = args[opti];
7990 opti++;
7991 if ("activities".equals(cmd) || "a".equals(cmd)) {
7992 synchronized (this) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08007993 dumpActivitiesLocked(fd, pw, args, opti, true, dumpClient, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007994 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08007995 return;
7996 } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08007997 String[] newArgs;
7998 String name;
7999 if (opti >= args.length) {
8000 name = null;
8001 newArgs = EMPTY_STRING_ARRAY;
8002 } else {
8003 name = args[opti];
8004 opti++;
8005 newArgs = new String[args.length - opti];
8006 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0,
8007 args.length - opti);
8008 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008009 synchronized (this) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008010 dumpBroadcastsLocked(fd, pw, args, opti, true, name);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008011 }
8012 return;
8013 } else if ("intents".equals(cmd) || "i".equals(cmd)) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008014 String[] newArgs;
8015 String name;
8016 if (opti >= args.length) {
8017 name = null;
8018 newArgs = EMPTY_STRING_ARRAY;
8019 } else {
8020 name = args[opti];
8021 opti++;
8022 newArgs = new String[args.length - opti];
8023 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0,
8024 args.length - opti);
8025 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008026 synchronized (this) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008027 dumpPendingIntentsLocked(fd, pw, args, opti, true, name);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008028 }
8029 return;
8030 } else if ("processes".equals(cmd) || "p".equals(cmd)) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008031 String[] newArgs;
8032 String name;
8033 if (opti >= args.length) {
8034 name = null;
8035 newArgs = EMPTY_STRING_ARRAY;
8036 } else {
8037 name = args[opti];
8038 opti++;
8039 newArgs = new String[args.length - opti];
8040 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0,
8041 args.length - opti);
8042 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008043 synchronized (this) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008044 dumpProcessesLocked(fd, pw, args, opti, true, name);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008045 }
8046 return;
Dianne Hackborn287952c2010-09-22 22:34:31 -07008047 } else if ("oom".equals(cmd) || "o".equals(cmd)) {
8048 synchronized (this) {
8049 dumpOomLocked(fd, pw, args, opti, true);
8050 }
8051 return;
Marco Nelissen18cb2872011-11-15 11:19:53 -08008052 } else if ("provider".equals(cmd)) {
8053 String[] newArgs;
8054 String name;
8055 if (opti >= args.length) {
8056 name = null;
8057 newArgs = EMPTY_STRING_ARRAY;
8058 } else {
8059 name = args[opti];
8060 opti++;
8061 newArgs = new String[args.length - opti];
8062 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
8063 }
8064 if (!dumpProvider(fd, pw, name, newArgs, 0, dumpAll)) {
8065 pw.println("No providers match: " + name);
8066 pw.println("Use -h for help.");
8067 }
8068 return;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008069 } else if ("providers".equals(cmd) || "prov".equals(cmd)) {
8070 synchronized (this) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008071 dumpProvidersLocked(fd, pw, args, opti, true, null);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008072 }
8073 return;
8074 } else if ("service".equals(cmd)) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008075 String[] newArgs;
8076 String name;
8077 if (opti >= args.length) {
8078 name = null;
8079 newArgs = EMPTY_STRING_ARRAY;
8080 } else {
8081 name = args[opti];
8082 opti++;
8083 newArgs = new String[args.length - opti];
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008084 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0,
8085 args.length - opti);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008086 }
8087 if (!dumpService(fd, pw, name, newArgs, 0, dumpAll)) {
8088 pw.println("No services match: " + name);
8089 pw.println("Use -h for help.");
8090 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008091 return;
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008092 } else if ("package".equals(cmd)) {
8093 String[] newArgs;
8094 if (opti >= args.length) {
8095 pw.println("package: no package name specified");
8096 pw.println("Use -h for help.");
8097 return;
8098 } else {
8099 dumpPackage = args[opti];
8100 opti++;
8101 newArgs = new String[args.length - opti];
8102 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0,
8103 args.length - opti);
8104 args = newArgs;
8105 opti = 0;
8106 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008107 } else if ("services".equals(cmd) || "s".equals(cmd)) {
8108 synchronized (this) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008109 dumpServicesLocked(fd, pw, args, opti, true, dumpClient, null);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008110 }
8111 return;
Dianne Hackborn625ac272010-09-17 18:29:22 -07008112 } else {
8113 // Dumping a single activity?
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008114 if (!dumpActivity(fd, pw, cmd, args, opti, dumpAll)) {
8115 pw.println("Bad activity command, or no activities match: " + cmd);
8116 pw.println("Use -h for help.");
Dianne Hackborn625ac272010-09-17 18:29:22 -07008117 }
Dianne Hackborn30d71892010-12-11 10:37:55 -08008118 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008119 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008120 }
8121
8122 // No piece of data specified, dump everything.
8123 synchronized (this) {
8124 boolean needSep;
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008125 needSep = dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll, dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008126 if (needSep) {
8127 pw.println(" ");
8128 }
8129 if (dumpAll) {
8130 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008131 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008132 needSep = dumpBroadcastsLocked(fd, pw, args, opti, dumpAll, dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008133 if (needSep) {
8134 pw.println(" ");
8135 }
8136 if (dumpAll) {
8137 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008138 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008139 needSep = dumpProvidersLocked(fd, pw, args, opti, dumpAll, dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008140 if (needSep) {
8141 pw.println(" ");
8142 }
8143 if (dumpAll) {
8144 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008145 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008146 needSep = dumpServicesLocked(fd, pw, args, opti, dumpAll, dumpClient, dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008147 if (needSep) {
8148 pw.println(" ");
8149 }
8150 if (dumpAll) {
8151 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008152 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008153 needSep = dumpActivitiesLocked(fd, pw, args, opti, dumpAll, dumpClient, dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008154 if (needSep) {
8155 pw.println(" ");
8156 }
8157 if (dumpAll) {
8158 pw.println("-------------------------------------------------------------------------------");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008159 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008160 dumpProcessesLocked(fd, pw, args, opti, dumpAll, dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008161 }
8162 }
8163
8164 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008165 int opti, boolean dumpAll, boolean dumpClient, String dumpPackage) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008166 pw.println("ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)");
8167 pw.println(" Main stack:");
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008168 dumpHistoryList(fd, pw, mMainStack.mHistory, " ", "Hist", true, !dumpAll, dumpClient,
8169 dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008170 pw.println(" ");
8171 pw.println(" Running activities (most recent first):");
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008172 dumpHistoryList(fd, pw, mMainStack.mLRUActivities, " ", "Run", false, !dumpAll, false,
8173 dumpPackage);
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008174 if (mMainStack.mWaitingVisibleActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008175 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008176 pw.println(" Activities waiting for another to become visible:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008177 dumpHistoryList(fd, pw, mMainStack.mWaitingVisibleActivities, " ", "Wait", false,
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008178 !dumpAll, false, dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008179 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008180 if (mMainStack.mStoppingActivities.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008181 pw.println(" ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008182 pw.println(" Activities waiting to stop:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008183 dumpHistoryList(fd, pw, mMainStack.mStoppingActivities, " ", "Stop", false,
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008184 !dumpAll, false, dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008185 }
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08008186 if (mMainStack.mGoingToSleepActivities.size() > 0) {
8187 pw.println(" ");
8188 pw.println(" Activities waiting to sleep:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008189 dumpHistoryList(fd, pw, mMainStack.mGoingToSleepActivities, " ", "Sleep", false,
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008190 !dumpAll, false, dumpPackage);
Dianne Hackborn4eba96b2011-01-21 13:34:36 -08008191 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008192 if (mMainStack.mFinishingActivities.size() > 0) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008193 pw.println(" ");
8194 pw.println(" Activities waiting to finish:");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008195 dumpHistoryList(fd, pw, mMainStack.mFinishingActivities, " ", "Fin", false,
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008196 !dumpAll, false, dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008197 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008198
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008199 pw.println(" ");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008200 if (mMainStack.mPausingActivity != null) {
8201 pw.println(" mPausingActivity: " + mMainStack.mPausingActivity);
8202 }
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008203 pw.println(" mResumedActivity: " + mMainStack.mResumedActivity);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008204 pw.println(" mFocusedActivity: " + mFocusedActivity);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008205 if (dumpAll) {
8206 pw.println(" mLastPausedActivity: " + mMainStack.mLastPausedActivity);
8207 pw.println(" mSleepTimeout: " + mMainStack.mSleepTimeout);
Dianne Hackborn90c52de2011-09-23 12:57:44 -07008208 pw.println(" mDismissKeyguardOnNextActivity: "
8209 + mMainStack.mDismissKeyguardOnNextActivity);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008210 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008211
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008212 if (mRecentTasks.size() > 0) {
8213 pw.println();
8214 pw.println(" Recent tasks:");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008215
8216 final int N = mRecentTasks.size();
8217 for (int i=0; i<N; i++) {
8218 TaskRecord tr = mRecentTasks.get(i);
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008219 if (dumpPackage != null) {
8220 if (tr.realActivity == null ||
8221 !dumpPackage.equals(tr.realActivity)) {
8222 continue;
8223 }
8224 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008225 pw.print(" * Recent #"); pw.print(i); pw.print(": ");
8226 pw.println(tr);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008227 if (dumpAll) {
8228 mRecentTasks.get(i).dump(pw, " ");
8229 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008230 }
8231 }
8232
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008233 if (dumpAll) {
8234 pw.println(" ");
8235 pw.println(" mCurTask: " + mCurTask);
8236 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008237
8238 return true;
8239 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07008240
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008241 boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008242 int opti, boolean dumpAll, String dumpPackage) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008243 boolean needSep = false;
8244 int numPers = 0;
8245
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008246 pw.println("ACTIVITY MANAGER RUNNING PROCESSES (dumpsys activity processes)");
8247
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008248 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008249 for (SparseArray<ProcessRecord> procs : mProcessNames.getMap().values()) {
8250 final int NA = procs.size();
8251 for (int ia=0; ia<NA; ia++) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008252 ProcessRecord r = procs.valueAt(ia);
8253 if (dumpPackage != null && !dumpPackage.equals(r.info.packageName)) {
8254 continue;
8255 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008256 if (!needSep) {
8257 pw.println(" All known processes:");
8258 needSep = true;
8259 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008260 pw.print(r.persistent ? " *PERS*" : " *APP*");
8261 pw.print(" UID "); pw.print(procs.keyAt(ia));
8262 pw.print(" "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008263 r.dump(pw, " ");
8264 if (r.persistent) {
8265 numPers++;
8266 }
8267 }
8268 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008269 }
8270
8271 if (mLruProcesses.size() > 0) {
8272 if (needSep) pw.println(" ");
8273 needSep = true;
Dianne Hackborn905577f2011-09-07 18:31:28 -07008274 pw.println(" Process LRU list (sorted by oom_adj):");
Dianne Hackborn287952c2010-09-22 22:34:31 -07008275 dumpProcessOomList(pw, this, mLruProcesses, " ",
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008276 "Proc", "PERS", false, dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008277 needSep = true;
8278 }
8279
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008280 if (dumpAll) {
8281 synchronized (mPidsSelfLocked) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008282 boolean printed = false;
8283 for (int i=0; i<mPidsSelfLocked.size(); i++) {
8284 ProcessRecord r = mPidsSelfLocked.valueAt(i);
8285 if (dumpPackage != null && !dumpPackage.equals(r.info.packageName)) {
8286 continue;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008287 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008288 if (!printed) {
8289 if (needSep) pw.println(" ");
8290 needSep = true;
8291 pw.println(" PID mappings:");
8292 printed = true;
8293 }
8294 pw.print(" PID #"); pw.print(mPidsSelfLocked.keyAt(i));
8295 pw.print(": "); pw.println(mPidsSelfLocked.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008296 }
8297 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008298 }
8299
8300 if (mForegroundProcesses.size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008301 synchronized (mPidsSelfLocked) {
8302 boolean printed = false;
8303 for (int i=0; i<mForegroundProcesses.size(); i++) {
8304 ProcessRecord r = mPidsSelfLocked.get(
8305 mForegroundProcesses.valueAt(i).pid);
8306 if (dumpPackage != null && (r == null
8307 || !dumpPackage.equals(r.info.packageName))) {
8308 continue;
8309 }
8310 if (!printed) {
8311 if (needSep) pw.println(" ");
8312 needSep = true;
8313 pw.println(" Foreground Processes:");
8314 printed = true;
8315 }
8316 pw.print(" PID #"); pw.print(mForegroundProcesses.keyAt(i));
8317 pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
8318 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008319 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008320 }
8321
8322 if (mPersistentStartingProcesses.size() > 0) {
8323 if (needSep) pw.println(" ");
8324 needSep = true;
8325 pw.println(" Persisent processes that are starting:");
8326 dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008327 "Starting Norm", "Restarting PERS", dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008328 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008329
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008330 if (mRemovedProcesses.size() > 0) {
8331 if (needSep) pw.println(" ");
8332 needSep = true;
8333 pw.println(" Processes that are being removed:");
8334 dumpProcessList(pw, this, mRemovedProcesses, " ",
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008335 "Removed Norm", "Removed PERS", dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008336 }
8337
8338 if (mProcessesOnHold.size() > 0) {
8339 if (needSep) pw.println(" ");
8340 needSep = true;
8341 pw.println(" Processes that are on old until the system is ready:");
8342 dumpProcessList(pw, this, mProcessesOnHold, " ",
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008343 "OnHold Norm", "OnHold PERS", dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008344 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008345
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008346 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll, dumpPackage);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008347
8348 if (mProcessCrashTimes.getMap().size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008349 boolean printed = false;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008350 long now = SystemClock.uptimeMillis();
8351 for (Map.Entry<String, SparseArray<Long>> procs
8352 : mProcessCrashTimes.getMap().entrySet()) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008353 String pname = procs.getKey();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008354 SparseArray<Long> uids = procs.getValue();
8355 final int N = uids.size();
8356 for (int i=0; i<N; i++) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008357 int puid = uids.keyAt(i);
8358 ProcessRecord r = mProcessNames.get(pname, puid);
8359 if (dumpPackage != null && (r == null
8360 || !dumpPackage.equals(r.info.packageName))) {
8361 continue;
8362 }
8363 if (!printed) {
8364 if (needSep) pw.println(" ");
8365 needSep = true;
8366 pw.println(" Time since processes crashed:");
8367 printed = true;
8368 }
8369 pw.print(" Process "); pw.print(pname);
8370 pw.print(" uid "); pw.print(puid);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008371 pw.print(": last crashed ");
8372 pw.print((now-uids.valueAt(i)));
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008373 pw.println(" ms ago");
Dianne Hackbornfd12af42009-08-27 00:44:33 -07008374 }
8375 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008376 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008377
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008378 if (mBadProcesses.getMap().size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008379 boolean printed = false;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008380 for (Map.Entry<String, SparseArray<Long>> procs
8381 : mBadProcesses.getMap().entrySet()) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008382 String pname = procs.getKey();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008383 SparseArray<Long> uids = procs.getValue();
8384 final int N = uids.size();
8385 for (int i=0; i<N; i++) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008386 int puid = uids.keyAt(i);
8387 ProcessRecord r = mProcessNames.get(pname, puid);
8388 if (dumpPackage != null && (r == null
8389 || !dumpPackage.equals(r.info.packageName))) {
8390 continue;
8391 }
8392 if (!printed) {
8393 if (needSep) pw.println(" ");
8394 needSep = true;
8395 pw.println(" Bad processes:");
8396 }
8397 pw.print(" Bad process "); pw.print(pname);
8398 pw.print(" uid "); pw.print(puid);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008399 pw.print(": crashed at time ");
8400 pw.println(uids.valueAt(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008401 }
8402 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008403 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008404
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008405 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008406 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackbornf35fe232011-11-01 19:25:20 -07008407 pw.println(" mPreviousProcess: " + mPreviousProcess);
Dianne Hackborn50685602011-12-01 12:23:37 -08008408 if (dumpAll) {
8409 StringBuilder sb = new StringBuilder(128);
8410 sb.append(" mPreviousProcessVisibleTime: ");
8411 TimeUtils.formatDuration(mPreviousProcessVisibleTime, sb);
8412 pw.println(sb);
8413 }
Dianne Hackborn860755f2010-06-03 18:47:52 -07008414 if (mHeavyWeightProcess != null) {
8415 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
8416 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008417 pw.println(" mConfiguration: " + mConfiguration);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008418 if (dumpAll) {
8419 pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
Dianne Hackborn3d0724d2011-05-12 15:39:41 -07008420 if (mCompatModePackages.getPackages().size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008421 boolean printed = false;
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07008422 for (Map.Entry<String, Integer> entry
8423 : mCompatModePackages.getPackages().entrySet()) {
8424 String pkg = entry.getKey();
8425 int mode = entry.getValue();
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008426 if (dumpPackage != null && !dumpPackage.equals(pkg)) {
8427 continue;
8428 }
8429 if (!printed) {
8430 pw.println(" mScreenCompatPackages:");
8431 printed = true;
8432 }
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07008433 pw.print(" "); pw.print(pkg); pw.print(": ");
8434 pw.print(mode); pw.println();
8435 }
Dianne Hackbornaa9d84c2011-05-09 19:00:59 -07008436 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008437 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008438 pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
8439 if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
8440 || mOrigWaitForDebugger) {
8441 pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp
8442 + " mDebugTransient=" + mDebugTransient
8443 + " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
8444 }
Dianne Hackborn62f20ec2011-08-15 17:40:28 -07008445 if (mProfileApp != null || mProfileProc != null || mProfileFile != null
8446 || mProfileFd != null) {
8447 pw.println(" mProfileApp=" + mProfileApp + " mProfileProc=" + mProfileProc);
8448 pw.println(" mProfileFile=" + mProfileFile + " mProfileFd=" + mProfileFd);
8449 pw.println(" mProfileType=" + mProfileType + " mAutoStopProfiler="
8450 + mAutoStopProfiler);
8451 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008452 if (mAlwaysFinishActivities || mController != null) {
8453 pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
8454 + " mController=" + mController);
8455 }
8456 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008457 pw.println(" Total persistent processes: " + numPers);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008458 pw.println(" mStartRunning=" + mStartRunning
Dianne Hackborn8891fdc2010-09-20 20:44:46 -07008459 + " mProcessesReady=" + mProcessesReady
8460 + " mSystemReady=" + mSystemReady);
8461 pw.println(" mBooting=" + mBooting
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008462 + " mBooted=" + mBooted
8463 + " mFactoryTest=" + mFactoryTest);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008464 pw.print(" mLastPowerCheckRealtime=");
8465 TimeUtils.formatDuration(mLastPowerCheckRealtime, pw);
8466 pw.println("");
8467 pw.print(" mLastPowerCheckUptime=");
8468 TimeUtils.formatDuration(mLastPowerCheckUptime, pw);
8469 pw.println("");
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -07008470 pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
8471 pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
Dianne Hackborn906497c2010-05-10 15:57:38 -07008472 pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
Dianne Hackborne02c88a2011-10-28 13:58:15 -07008473 pw.println(" mNumServiceProcs=" + mNumServiceProcs
8474 + " mNewNumServiceProcs=" + mNewNumServiceProcs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008475 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008476
8477 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008478 }
8479
Dianne Hackborn287952c2010-09-22 22:34:31 -07008480 boolean dumpProcessesToGc(FileDescriptor fd, PrintWriter pw, String[] args,
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008481 int opti, boolean needSep, boolean dumpAll, String dumpPackage) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07008482 if (mProcessesToGc.size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008483 boolean printed = false;
Dianne Hackborn287952c2010-09-22 22:34:31 -07008484 long now = SystemClock.uptimeMillis();
8485 for (int i=0; i<mProcessesToGc.size(); i++) {
8486 ProcessRecord proc = mProcessesToGc.get(i);
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008487 if (dumpPackage != null && !dumpPackage.equals(proc.info.packageName)) {
8488 continue;
8489 }
8490 if (!printed) {
8491 if (needSep) pw.println(" ");
8492 needSep = true;
8493 pw.println(" Processes that are waiting to GC:");
8494 printed = true;
8495 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07008496 pw.print(" Process "); pw.println(proc);
8497 pw.print(" lowMem="); pw.print(proc.reportLowMemory);
8498 pw.print(", last gced=");
8499 pw.print(now-proc.lastRequestedGc);
8500 pw.print(" ms ago, last lowMem=");
8501 pw.print(now-proc.lastLowMemory);
8502 pw.println(" ms ago");
8503
8504 }
8505 }
8506 return needSep;
8507 }
8508
8509 boolean dumpOomLocked(FileDescriptor fd, PrintWriter pw, String[] args,
8510 int opti, boolean dumpAll) {
8511 boolean needSep = false;
8512
8513 if (mLruProcesses.size() > 0) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07008514 if (needSep) pw.println(" ");
8515 needSep = true;
Dianne Hackbornc68c9132011-07-29 01:25:18 -07008516 pw.println(" OOM levels:");
Dianne Hackborn7d608422011-08-07 16:24:18 -07008517 pw.print(" SYSTEM_ADJ: "); pw.println(ProcessList.SYSTEM_ADJ);
Dianne Hackborne02c88a2011-10-28 13:58:15 -07008518 pw.print(" PERSISTENT_PROC_ADJ: "); pw.println(ProcessList.PERSISTENT_PROC_ADJ);
Dianne Hackborn7d608422011-08-07 16:24:18 -07008519 pw.print(" FOREGROUND_APP_ADJ: "); pw.println(ProcessList.FOREGROUND_APP_ADJ);
8520 pw.print(" VISIBLE_APP_ADJ: "); pw.println(ProcessList.VISIBLE_APP_ADJ);
8521 pw.print(" PERCEPTIBLE_APP_ADJ: "); pw.println(ProcessList.PERCEPTIBLE_APP_ADJ);
8522 pw.print(" HEAVY_WEIGHT_APP_ADJ: "); pw.println(ProcessList.HEAVY_WEIGHT_APP_ADJ);
8523 pw.print(" BACKUP_APP_ADJ: "); pw.println(ProcessList.BACKUP_APP_ADJ);
Dianne Hackborne02c88a2011-10-28 13:58:15 -07008524 pw.print(" SERVICE_ADJ: "); pw.println(ProcessList.SERVICE_ADJ);
Dianne Hackborn7d608422011-08-07 16:24:18 -07008525 pw.print(" HOME_APP_ADJ: "); pw.println(ProcessList.HOME_APP_ADJ);
Dianne Hackbornf35fe232011-11-01 19:25:20 -07008526 pw.print(" PREVIOUS_APP_ADJ: "); pw.println(ProcessList.PREVIOUS_APP_ADJ);
Dianne Hackborne02c88a2011-10-28 13:58:15 -07008527 pw.print(" SERVICE_B_ADJ: "); pw.println(ProcessList.SERVICE_B_ADJ);
Dianne Hackborn7d608422011-08-07 16:24:18 -07008528 pw.print(" HIDDEN_APP_MIN_ADJ: "); pw.println(ProcessList.HIDDEN_APP_MIN_ADJ);
Dianne Hackborne02c88a2011-10-28 13:58:15 -07008529 pw.print(" HIDDEN_APP_MAX_ADJ: "); pw.println(ProcessList.HIDDEN_APP_MAX_ADJ);
Dianne Hackbornc68c9132011-07-29 01:25:18 -07008530
8531 if (needSep) pw.println(" ");
8532 needSep = true;
Dianne Hackborn287952c2010-09-22 22:34:31 -07008533 pw.println(" Process OOM control:");
Dianne Hackborn905577f2011-09-07 18:31:28 -07008534 dumpProcessOomList(pw, this, mLruProcesses, " ",
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008535 "Proc", "PERS", true, null);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008536 needSep = true;
8537 }
8538
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008539 needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll, null);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008540
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008541 pw.println();
Dianne Hackborn287952c2010-09-22 22:34:31 -07008542 pw.println(" mHomeProcess: " + mHomeProcess);
Dianne Hackbornf35fe232011-11-01 19:25:20 -07008543 pw.println(" mPreviousProcess: " + mPreviousProcess);
Dianne Hackborn287952c2010-09-22 22:34:31 -07008544 if (mHeavyWeightProcess != null) {
8545 pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
8546 }
8547
8548 return true;
8549 }
8550
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008551 /**
8552 * There are three ways to call this:
8553 * - no service specified: dump all the services
8554 * - a flattened component name that matched an existing service was specified as the
8555 * first arg: dump that one service
8556 * - the first arg isn't the flattened component name of an existing service:
8557 * dump all services whose component contains the first arg as a substring
8558 */
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008559 protected boolean dumpService(FileDescriptor fd, PrintWriter pw, String name, String[] args,
8560 int opti, boolean dumpAll) {
8561 ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008562
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008563 if ("all".equals(name)) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07008564 synchronized (this) {
8565 for (ServiceRecord r1 : mServices.values()) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008566 services.add(r1);
8567 }
8568 }
8569 } else {
8570 ComponentName componentName = name != null
8571 ? ComponentName.unflattenFromString(name) : null;
8572 int objectId = 0;
8573 if (componentName == null) {
8574 // Not a '/' separated full component name; maybe an object ID?
8575 try {
8576 objectId = Integer.parseInt(name, 16);
8577 name = null;
8578 componentName = null;
8579 } catch (RuntimeException e) {
8580 }
8581 }
8582
8583 synchronized (this) {
8584 for (ServiceRecord r1 : mServices.values()) {
8585 if (componentName != null) {
8586 if (r1.name.equals(componentName)) {
8587 services.add(r1);
8588 }
8589 } else if (name != null) {
8590 if (r1.name.flattenToString().contains(name)) {
8591 services.add(r1);
8592 }
8593 } else if (System.identityHashCode(r1) == objectId) {
Dianne Hackborn14bfa392010-07-24 19:58:06 -07008594 services.add(r1);
8595 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008596 }
8597 }
8598 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008599
8600 if (services.size() <= 0) {
8601 return false;
8602 }
8603
8604 boolean needSep = false;
8605 for (int i=0; i<services.size(); i++) {
8606 if (needSep) {
8607 pw.println();
8608 }
8609 needSep = true;
8610 dumpService("", fd, pw, services.get(i), args, dumpAll);
8611 }
8612 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008613 }
8614
8615 /**
8616 * Invokes IApplicationThread.dumpService() on the thread of the specified service if
8617 * there is a thread associated with the service.
8618 */
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008619 private void dumpService(String prefix, FileDescriptor fd, PrintWriter pw,
8620 final ServiceRecord r, String[] args, boolean dumpAll) {
8621 String innerPrefix = prefix + " ";
8622 synchronized (this) {
8623 pw.print(prefix); pw.print("SERVICE ");
8624 pw.print(r.shortName); pw.print(" ");
8625 pw.print(Integer.toHexString(System.identityHashCode(r)));
8626 pw.print(" pid=");
8627 if (r.app != null) pw.println(r.app.pid);
8628 else pw.println("(not running)");
8629 if (dumpAll) {
8630 r.dump(pw, innerPrefix);
8631 }
8632 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008633 if (r.app != null && r.app.thread != null) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008634 pw.print(prefix); pw.println(" Client:");
8635 pw.flush();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008636 try {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008637 TransferPipe tp = new TransferPipe();
8638 try {
8639 r.app.thread.dumpService(tp.getWriteFd().getFileDescriptor(), r, args);
8640 tp.setBufferPrefix(prefix + " ");
8641 tp.go(fd);
8642 } finally {
8643 tp.kill();
8644 }
8645 } catch (IOException e) {
8646 pw.println(prefix + " Failure while dumping the service: " + e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008647 } catch (RemoteException e) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008648 pw.println(prefix + " Got a RemoteException while dumping the service");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008649 }
8650 }
8651 }
8652
Marco Nelissen18cb2872011-11-15 11:19:53 -08008653 /**
8654 * There are three ways to call this:
8655 * - no provider specified: dump all the providers
8656 * - a flattened component name that matched an existing provider was specified as the
8657 * first arg: dump that one provider
8658 * - the first arg isn't the flattened component name of an existing provider:
8659 * dump all providers whose component contains the first arg as a substring
8660 */
8661 protected boolean dumpProvider(FileDescriptor fd, PrintWriter pw, String name, String[] args,
8662 int opti, boolean dumpAll) {
8663 ArrayList<ContentProviderRecord> providers = new ArrayList<ContentProviderRecord>();
8664
8665 if ("all".equals(name)) {
8666 synchronized (this) {
8667 for (ContentProviderRecord r1 : mProvidersByClass.values()) {
8668 providers.add(r1);
8669 }
8670 }
8671 } else {
8672 ComponentName componentName = name != null
8673 ? ComponentName.unflattenFromString(name) : null;
8674 int objectId = 0;
8675 if (componentName == null) {
8676 // Not a '/' separated full component name; maybe an object ID?
8677 try {
8678 objectId = Integer.parseInt(name, 16);
8679 name = null;
8680 componentName = null;
8681 } catch (RuntimeException e) {
8682 }
8683 }
8684
8685 synchronized (this) {
8686 for (ContentProviderRecord r1 : mProvidersByClass.values()) {
8687 if (componentName != null) {
8688 if (r1.name.equals(componentName)) {
8689 providers.add(r1);
8690 }
8691 } else if (name != null) {
8692 if (r1.name.flattenToString().contains(name)) {
8693 providers.add(r1);
8694 }
8695 } else if (System.identityHashCode(r1) == objectId) {
8696 providers.add(r1);
8697 }
8698 }
8699 }
8700 }
8701
8702 if (providers.size() <= 0) {
8703 return false;
8704 }
8705
8706 boolean needSep = false;
8707 for (int i=0; i<providers.size(); i++) {
8708 if (needSep) {
8709 pw.println();
8710 }
8711 needSep = true;
8712 dumpProvider("", fd, pw, providers.get(i), args, dumpAll);
8713 }
8714 return true;
8715 }
8716
8717 /**
8718 * Invokes IApplicationThread.dumpProvider() on the thread of the specified provider if
8719 * there is a thread associated with the provider.
8720 */
8721 private void dumpProvider(String prefix, FileDescriptor fd, PrintWriter pw,
8722 final ContentProviderRecord r, String[] args, boolean dumpAll) {
8723 String innerPrefix = prefix + " ";
8724 synchronized (this) {
8725 pw.print(prefix); pw.print("PROVIDER ");
8726 pw.print(r);
8727 pw.print(" pid=");
8728 if (r.proc != null) pw.println(r.proc.pid);
8729 else pw.println("(not running)");
8730 if (dumpAll) {
8731 r.dump(pw, innerPrefix);
8732 }
8733 }
8734 if (r.proc != null && r.proc.thread != null) {
8735 pw.println(" Client:");
8736 pw.flush();
8737 try {
8738 TransferPipe tp = new TransferPipe();
8739 try {
8740 r.proc.thread.dumpProvider(
8741 tp.getWriteFd().getFileDescriptor(), r.provider.asBinder(), args);
8742 tp.setBufferPrefix(" ");
8743 // Short timeout, since blocking here can
8744 // deadlock with the application.
8745 tp.go(fd, 2000);
8746 } finally {
8747 tp.kill();
8748 }
8749 } catch (IOException ex) {
8750 pw.println(" Failure while dumping the provider: " + ex);
8751 } catch (RemoteException ex) {
8752 pw.println(" Got a RemoteException while dumping the service");
8753 }
8754 }
8755 }
8756
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07008757 static class ItemMatcher {
8758 ArrayList<ComponentName> components;
8759 ArrayList<String> strings;
8760 ArrayList<Integer> objects;
8761 boolean all;
8762
8763 ItemMatcher() {
8764 all = true;
8765 }
8766
8767 void build(String name) {
8768 ComponentName componentName = ComponentName.unflattenFromString(name);
8769 if (componentName != null) {
8770 if (components == null) {
8771 components = new ArrayList<ComponentName>();
8772 }
8773 components.add(componentName);
8774 all = false;
8775 } else {
8776 int objectId = 0;
8777 // Not a '/' separated full component name; maybe an object ID?
8778 try {
8779 objectId = Integer.parseInt(name, 16);
8780 if (objects == null) {
8781 objects = new ArrayList<Integer>();
8782 }
8783 objects.add(objectId);
8784 all = false;
8785 } catch (RuntimeException e) {
8786 // Not an integer; just do string match.
8787 if (strings == null) {
8788 strings = new ArrayList<String>();
8789 }
8790 strings.add(name);
8791 all = false;
8792 }
8793 }
8794 }
8795
8796 int build(String[] args, int opti) {
8797 for (; opti<args.length; opti++) {
8798 String name = args[opti];
8799 if ("--".equals(name)) {
8800 return opti+1;
8801 }
8802 build(name);
8803 }
8804 return opti;
8805 }
8806
8807 boolean match(Object object, ComponentName comp) {
8808 if (all) {
8809 return true;
8810 }
8811 if (components != null) {
8812 for (int i=0; i<components.size(); i++) {
8813 if (components.get(i).equals(comp)) {
8814 return true;
8815 }
8816 }
8817 }
8818 if (objects != null) {
8819 for (int i=0; i<objects.size(); i++) {
8820 if (System.identityHashCode(object) == objects.get(i)) {
8821 return true;
8822 }
8823 }
8824 }
8825 if (strings != null) {
8826 String flat = comp.flattenToString();
8827 for (int i=0; i<strings.size(); i++) {
8828 if (flat.contains(strings.get(i))) {
8829 return true;
8830 }
8831 }
8832 }
8833 return false;
8834 }
8835 }
8836
Dianne Hackborn625ac272010-09-17 18:29:22 -07008837 /**
8838 * There are three things that cmd can be:
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07008839 * - a flattened component name that matches an existing activity
Dianne Hackborn625ac272010-09-17 18:29:22 -07008840 * - the cmd arg isn't the flattened component name of an existing activity:
8841 * dump all activity whose component contains the cmd as a substring
8842 * - A hex number of the ActivityRecord object instance.
8843 */
8844 protected boolean dumpActivity(FileDescriptor fd, PrintWriter pw, String name, String[] args,
8845 int opti, boolean dumpAll) {
Dianne Hackborn625ac272010-09-17 18:29:22 -07008846 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008847
8848 if ("all".equals(name)) {
8849 synchronized (this) {
8850 for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
Dianne Hackborn625ac272010-09-17 18:29:22 -07008851 activities.add(r1);
8852 }
8853 }
Dianne Hackbornf9302322011-06-14 18:36:14 -07008854 } else if ("top".equals(name)) {
8855 synchronized (this) {
8856 final int N = mMainStack.mHistory.size();
8857 if (N > 0) {
8858 activities.add((ActivityRecord)mMainStack.mHistory.get(N-1));
8859 }
8860 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008861 } else {
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07008862 ItemMatcher matcher = new ItemMatcher();
8863 matcher.build(name);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008864
8865 synchronized (this) {
8866 for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07008867 if (matcher.match(r1, r1.intent.getComponent())) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008868 activities.add(r1);
8869 }
8870 }
8871 }
Dianne Hackborn625ac272010-09-17 18:29:22 -07008872 }
8873
8874 if (activities.size() <= 0) {
8875 return false;
8876 }
8877
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008878 String[] newArgs = new String[args.length - opti];
8879 if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
8880
Dianne Hackborn30d71892010-12-11 10:37:55 -08008881 TaskRecord lastTask = null;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008882 boolean needSep = false;
Dianne Hackborn30d71892010-12-11 10:37:55 -08008883 for (int i=activities.size()-1; i>=0; i--) {
8884 ActivityRecord r = (ActivityRecord)activities.get(i);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008885 if (needSep) {
8886 pw.println();
8887 }
8888 needSep = true;
8889 synchronized (this) {
8890 if (lastTask != r.task) {
8891 lastTask = r.task;
8892 pw.print("TASK "); pw.print(lastTask.affinity);
8893 pw.print(" id="); pw.println(lastTask.taskId);
8894 if (dumpAll) {
8895 lastTask.dump(pw, " ");
8896 }
Dianne Hackborn30d71892010-12-11 10:37:55 -08008897 }
8898 }
8899 dumpActivity(" ", fd, pw, activities.get(i), newArgs, dumpAll);
Dianne Hackborn625ac272010-09-17 18:29:22 -07008900 }
8901 return true;
8902 }
8903
8904 /**
8905 * Invokes IApplicationThread.dumpActivity() on the thread of the specified activity if
8906 * there is a thread associated with the activity.
8907 */
Dianne Hackborn30d71892010-12-11 10:37:55 -08008908 private void dumpActivity(String prefix, FileDescriptor fd, PrintWriter pw,
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008909 final ActivityRecord r, String[] args, boolean dumpAll) {
8910 String innerPrefix = prefix + " ";
Dianne Hackborn30d71892010-12-11 10:37:55 -08008911 synchronized (this) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008912 pw.print(prefix); pw.print("ACTIVITY "); pw.print(r.shortComponentName);
8913 pw.print(" "); pw.print(Integer.toHexString(System.identityHashCode(r)));
8914 pw.print(" pid=");
Dianne Hackborn30d71892010-12-11 10:37:55 -08008915 if (r.app != null) pw.println(r.app.pid);
8916 else pw.println("(not running)");
8917 if (dumpAll) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008918 r.dump(pw, innerPrefix);
Dianne Hackborn625ac272010-09-17 18:29:22 -07008919 }
Dianne Hackborn625ac272010-09-17 18:29:22 -07008920 }
8921 if (r.app != null && r.app.thread != null) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008922 // flush anything that is already in the PrintWriter since the thread is going
8923 // to write to the file descriptor directly
8924 pw.flush();
Dianne Hackborn625ac272010-09-17 18:29:22 -07008925 try {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008926 TransferPipe tp = new TransferPipe();
8927 try {
Dianne Hackbornbe707852011-11-11 14:32:10 -08008928 r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(),
8929 r.appToken, innerPrefix, args);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008930 tp.go(fd);
8931 } finally {
8932 tp.kill();
8933 }
8934 } catch (IOException e) {
8935 pw.println(innerPrefix + "Failure while dumping the activity: " + e);
Dianne Hackborn625ac272010-09-17 18:29:22 -07008936 } catch (RemoteException e) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008937 pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
Dianne Hackborn625ac272010-09-17 18:29:22 -07008938 }
8939 }
8940 }
8941
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008942 boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008943 int opti, boolean dumpAll, String dumpPackage) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008944 boolean needSep = false;
8945
Dianne Hackborne17aeb32011-04-07 15:11:57 -07008946 pw.println("ACTIVITY MANAGER BROADCAST STATE (dumpsys activity broadcasts)");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008947 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008948 if (mRegisteredReceivers.size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008949 boolean printed = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008950 Iterator it = mRegisteredReceivers.values().iterator();
8951 while (it.hasNext()) {
8952 ReceiverList r = (ReceiverList)it.next();
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008953 if (dumpPackage != null && (r.app == null ||
8954 !dumpPackage.equals(r.app.info.packageName))) {
8955 continue;
8956 }
8957 if (!printed) {
8958 pw.println(" Registered Receivers:");
8959 needSep = true;
8960 printed = true;
8961 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008962 pw.print(" * "); pw.println(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008963 r.dump(pw, " ");
8964 }
8965 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008966
8967 if (mReceiverResolver.dump(pw, needSep ?
8968 "\n Receiver Resolver Table:" : " Receiver Resolver Table:",
8969 " ", dumpPackage, false)) {
8970 needSep = true;
8971 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008972 }
8973
8974 if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0
8975 || mPendingBroadcast != null) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008976 boolean printed = false;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008977 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008978 BroadcastRecord br = mParallelBroadcasts.get(i);
8979 if (dumpPackage != null && !dumpPackage.equals(br.callerPackage)) {
8980 continue;
8981 }
8982 if (!printed) {
8983 if (needSep) {
8984 pw.println();
8985 }
8986 needSep = true;
8987 pw.println(" Active broadcasts:");
8988 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008989 pw.println(" Broadcast #" + i + ":");
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008990 br.dump(pw, " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008991 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008992 printed = false;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08008993 for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008994 BroadcastRecord br = mOrderedBroadcasts.get(i);
8995 if (dumpPackage != null && !dumpPackage.equals(br.callerPackage)) {
8996 continue;
8997 }
8998 if (!printed) {
8999 if (needSep) {
9000 pw.println();
9001 }
9002 needSep = true;
9003 pw.println(" Active ordered broadcasts:");
9004 }
9005 pw.println(" Ordered Broadcast #" + i + ":");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009006 mOrderedBroadcasts.get(i).dump(pw, " ");
9007 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009008 if (dumpPackage == null || (mPendingBroadcast != null
9009 && dumpPackage.equals(mPendingBroadcast.callerPackage))) {
9010 if (needSep) {
9011 pw.println();
9012 }
9013 pw.println(" Pending broadcast:");
9014 if (mPendingBroadcast != null) {
9015 mPendingBroadcast.dump(pw, " ");
9016 } else {
9017 pw.println(" (null)");
9018 }
9019 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009020 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009021 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009022
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009023 boolean printed = false;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009024 for (int i=0; i<MAX_BROADCAST_HISTORY; i++) {
9025 BroadcastRecord r = mBroadcastHistory[i];
9026 if (r == null) {
9027 break;
9028 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009029 if (dumpPackage != null && !dumpPackage.equals(r.callerPackage)) {
9030 continue;
9031 }
9032 if (!printed) {
9033 if (needSep) {
9034 pw.println();
9035 }
9036 needSep = true;
9037 pw.println(" Historical broadcasts:");
9038 printed = true;
9039 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009040 if (dumpAll) {
9041 pw.print(" Historical Broadcast #"); pw.print(i); pw.println(":");
9042 r.dump(pw, " ");
9043 } else {
9044 if (i >= 50) {
9045 pw.println(" ...");
Dianne Hackborn12527f92009-11-11 17:39:50 -08009046 break;
9047 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009048 pw.print(" #"); pw.print(i); pw.print(": "); pw.println(r);
Dianne Hackborn12527f92009-11-11 17:39:50 -08009049 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009050 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009051 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009052
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009053 if (mStickyBroadcasts != null && dumpPackage == null) {
9054 if (needSep) {
9055 pw.println();
9056 }
9057 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009058 pw.println(" Sticky broadcasts:");
9059 StringBuilder sb = new StringBuilder(128);
9060 for (Map.Entry<String, ArrayList<Intent>> ent
9061 : mStickyBroadcasts.entrySet()) {
9062 pw.print(" * Sticky action "); pw.print(ent.getKey());
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009063 if (dumpAll) {
9064 pw.println(":");
9065 ArrayList<Intent> intents = ent.getValue();
9066 final int N = intents.size();
9067 for (int i=0; i<N; i++) {
9068 sb.setLength(0);
9069 sb.append(" Intent: ");
Dianne Hackborn90c52de2011-09-23 12:57:44 -07009070 intents.get(i).toShortString(sb, false, true, false);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009071 pw.println(sb.toString());
9072 Bundle bundle = intents.get(i).getExtras();
9073 if (bundle != null) {
9074 pw.print(" ");
9075 pw.println(bundle.toString());
9076 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009077 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009078 } else {
9079 pw.println("");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009080 }
9081 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009082 needSep = true;
9083 }
9084
9085 if (dumpAll) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009086 pw.println();
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009087 pw.println(" mBroadcastsScheduled=" + mBroadcastsScheduled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009088 pw.println(" mHandler:");
9089 mHandler.dump(new PrintWriterPrinter(pw), " ");
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009090 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009091 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009092
9093 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009094 }
9095
Marco Nelissen18cb2872011-11-15 11:19:53 -08009096 /**
9097 * Prints a list of ServiceRecords (dumpsys activity services)
9098 */
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009099 boolean dumpServicesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009100 int opti, boolean dumpAll, boolean dumpClient, String dumpPackage) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009101 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009102
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07009103 ItemMatcher matcher = new ItemMatcher();
9104 matcher.build(args, opti);
9105
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009106 pw.println("ACTIVITY MANAGER SERVICES (dumpsys activity services)");
9107 if (mServices.size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009108 boolean printed = false;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009109 long nowReal = SystemClock.elapsedRealtime();
9110 Iterator<ServiceRecord> it = mServices.values().iterator();
9111 needSep = false;
9112 while (it.hasNext()) {
9113 ServiceRecord r = it.next();
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07009114 if (!matcher.match(r, r.name)) {
9115 continue;
9116 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009117 if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
9118 continue;
9119 }
9120 if (!printed) {
9121 pw.println(" Active services:");
9122 printed = true;
9123 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009124 if (needSep) {
9125 pw.println();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009126 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009127 pw.print(" * "); pw.println(r);
9128 if (dumpAll) {
9129 r.dump(pw, " ");
9130 needSep = true;
9131 } else {
9132 pw.print(" app="); pw.println(r.app);
9133 pw.print(" created=");
9134 TimeUtils.formatDuration(r.createTime, nowReal, pw);
9135 pw.print(" started="); pw.print(r.startRequested);
9136 pw.print(" connections="); pw.println(r.connections.size());
Dianne Hackborn8ec8d412011-11-14 18:27:24 -08009137 if (r.connections.size() > 0) {
9138 pw.println(" Connections:");
9139 for (ArrayList<ConnectionRecord> clist : r.connections.values()) {
9140 for (int i=0; i<clist.size(); i++) {
9141 ConnectionRecord conn = clist.get(i);
9142 pw.print(" ");
9143 pw.print(conn.binding.intent.intent.getIntent().toShortString(
9144 false, false, false));
9145 pw.print(" -> ");
9146 ProcessRecord proc = conn.binding.client;
9147 pw.println(proc != null ? proc.toShortString() : "null");
9148 }
9149 }
9150 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009151 }
9152 if (dumpClient && r.app != null && r.app.thread != null) {
9153 pw.println(" Client:");
9154 pw.flush();
9155 try {
9156 TransferPipe tp = new TransferPipe();
9157 try {
9158 r.app.thread.dumpService(
9159 tp.getWriteFd().getFileDescriptor(), r, args);
9160 tp.setBufferPrefix(" ");
9161 // Short timeout, since blocking here can
9162 // deadlock with the application.
9163 tp.go(fd, 2000);
9164 } finally {
9165 tp.kill();
9166 }
9167 } catch (IOException e) {
9168 pw.println(" Failure while dumping the service: " + e);
9169 } catch (RemoteException e) {
9170 pw.println(" Got a RemoteException while dumping the service");
9171 }
9172 needSep = true;
9173 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009174 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009175 needSep = printed;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009176 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009177
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009178 if (mPendingServices.size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009179 boolean printed = false;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009180 for (int i=0; i<mPendingServices.size(); i++) {
9181 ServiceRecord r = mPendingServices.get(i);
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07009182 if (!matcher.match(r, r.name)) {
9183 continue;
9184 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009185 if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
9186 continue;
9187 }
9188 if (!printed) {
9189 if (needSep) pw.println(" ");
9190 needSep = true;
9191 pw.println(" Pending services:");
9192 printed = true;
9193 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009194 pw.print(" * Pending "); pw.println(r);
9195 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009196 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009197 needSep = true;
9198 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009199
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009200 if (mRestartingServices.size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009201 boolean printed = false;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009202 for (int i=0; i<mRestartingServices.size(); i++) {
9203 ServiceRecord r = mRestartingServices.get(i);
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07009204 if (!matcher.match(r, r.name)) {
9205 continue;
9206 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009207 if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
9208 continue;
9209 }
9210 if (!printed) {
9211 if (needSep) pw.println(" ");
9212 needSep = true;
9213 pw.println(" Restarting services:");
9214 printed = true;
9215 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009216 pw.print(" * Restarting "); pw.println(r);
9217 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009218 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009219 needSep = true;
9220 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009221
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009222 if (mStoppingServices.size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009223 boolean printed = false;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009224 for (int i=0; i<mStoppingServices.size(); i++) {
9225 ServiceRecord r = mStoppingServices.get(i);
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07009226 if (!matcher.match(r, r.name)) {
9227 continue;
9228 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009229 if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
9230 continue;
9231 }
9232 if (!printed) {
9233 if (needSep) pw.println(" ");
9234 needSep = true;
9235 pw.println(" Stopping services:");
9236 printed = true;
9237 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009238 pw.print(" * Stopping "); pw.println(r);
9239 r.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009240 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009241 needSep = true;
9242 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009243
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009244 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009245 if (mServiceConnections.size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009246 boolean printed = false;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009247 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009248 = mServiceConnections.values().iterator();
9249 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009250 ArrayList<ConnectionRecord> r = it.next();
9251 for (int i=0; i<r.size(); i++) {
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07009252 ConnectionRecord cr = r.get(i);
9253 if (!matcher.match(cr.binding.service, cr.binding.service.name)) {
9254 continue;
9255 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009256 if (dumpPackage != null && (cr.binding.client == null
9257 || !dumpPackage.equals(cr.binding.client.info.packageName))) {
9258 continue;
9259 }
9260 if (!printed) {
9261 if (needSep) pw.println(" ");
9262 needSep = true;
9263 pw.println(" Connection bindings to services:");
9264 printed = true;
9265 }
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07009266 pw.print(" * "); pw.println(cr);
9267 cr.dump(pw, " ");
Dianne Hackborn43d9ac82010-08-25 15:06:25 -07009268 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009269 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009270 needSep = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009271 }
9272 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009273
9274 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009275 }
9276
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009277 boolean dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009278 int opti, boolean dumpAll, String dumpPackage) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009279 boolean needSep = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009280
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07009281 ItemMatcher matcher = new ItemMatcher();
9282 matcher.build(args, opti);
9283
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009284 pw.println("ACTIVITY MANAGER CONTENT PROVIDERS (dumpsys activity providers)");
9285 if (mProvidersByClass.size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009286 boolean printed = false;
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07009287 Iterator<Map.Entry<ComponentName, ContentProviderRecord>> it
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009288 = mProvidersByClass.entrySet().iterator();
9289 while (it.hasNext()) {
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07009290 Map.Entry<ComponentName, ContentProviderRecord> e = it.next();
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009291 ContentProviderRecord r = e.getValue();
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07009292 ComponentName comp = e.getKey();
9293 String cls = comp.getClassName();
9294 int end = cls.lastIndexOf('.');
9295 if (end > 0 && end < (cls.length()-2)) {
9296 cls = cls.substring(end+1);
9297 }
9298 if (!matcher.match(r, comp)) {
9299 continue;
9300 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009301 if (dumpPackage != null && !dumpPackage.equals(comp.getPackageName())) {
9302 continue;
9303 }
9304 if (!printed) {
9305 if (needSep) pw.println(" ");
9306 needSep = true;
9307 pw.println(" Published content providers (by class):");
9308 printed = true;
9309 }
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07009310 pw.print(" * "); pw.print(cls); pw.print(" (");
Dianne Hackborn8ec8d412011-11-14 18:27:24 -08009311 pw.print(comp.flattenToShortString()); pw.println(")");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009312 if (dumpAll) {
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07009313 r.dump(pw, " ");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009314 } else {
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07009315 if (r.proc != null) {
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -07009316 pw.print(" "); pw.println(r.proc);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009317 } else {
9318 pw.println();
9319 }
Dianne Hackborn8ec8d412011-11-14 18:27:24 -08009320 if (r.clients.size() > 0) {
9321 pw.println(" Clients:");
9322 for (ProcessRecord cproc : r.clients) {
9323 pw.print(" - "); pw.println(cproc);
9324 }
9325 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009326 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009327 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009328 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009329
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009330 if (dumpAll) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009331 if (mProvidersByName.size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009332 boolean printed = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -07009333 Iterator<Map.Entry<String, ContentProviderRecord>> it
9334 = mProvidersByName.entrySet().iterator();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009335 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -07009336 Map.Entry<String, ContentProviderRecord> e = it.next();
9337 ContentProviderRecord r = e.getValue();
Dianne Hackborn1c9b2602011-08-19 14:08:43 -07009338 if (!matcher.match(r, r.name)) {
9339 continue;
9340 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009341 if (dumpPackage != null && !dumpPackage.equals(r.name.getPackageName())) {
9342 continue;
9343 }
9344 if (!printed) {
9345 if (needSep) pw.println(" ");
9346 needSep = true;
9347 pw.println(" Authority to provider mappings:");
9348 printed = true;
9349 }
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -08009350 pw.print(" "); pw.print(e.getKey()); pw.println(":");
9351 pw.print(" "); pw.println(r);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009352 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009353 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009354 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009355
9356 if (mLaunchingProviders.size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009357 boolean printed = false;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009358 for (int i=mLaunchingProviders.size()-1; i>=0; i--) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009359 ContentProviderRecord r = mLaunchingProviders.get(i);
9360 if (dumpPackage != null && !dumpPackage.equals(r.name.getPackageName())) {
9361 continue;
9362 }
9363 if (!printed) {
9364 if (needSep) pw.println(" ");
9365 needSep = true;
9366 pw.println(" Launching content providers:");
9367 printed = true;
9368 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009369 pw.print(" Launching #"); pw.print(i); pw.print(": ");
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009370 pw.println(r);
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009371 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009372 }
9373
9374 if (mGrantedUriPermissions.size() > 0) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009375 if (needSep) pw.println();
9376 needSep = true;
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009377 pw.println("Granted Uri Permissions:");
9378 for (int i=0; i<mGrantedUriPermissions.size(); i++) {
9379 int uid = mGrantedUriPermissions.keyAt(i);
9380 HashMap<Uri, UriPermission> perms
9381 = mGrantedUriPermissions.valueAt(i);
9382 pw.print(" * UID "); pw.print(uid);
9383 pw.println(" holds:");
9384 for (UriPermission perm : perms.values()) {
9385 pw.print(" "); pw.println(perm);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009386 if (dumpAll) {
9387 perm.dump(pw, " ");
9388 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009389 }
9390 }
9391 needSep = true;
9392 }
9393
9394 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009395 }
9396
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009397 boolean dumpPendingIntentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009398 int opti, boolean dumpAll, String dumpPackage) {
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009399 boolean needSep = false;
9400
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009401 if (mIntentSenderRecords.size() > 0) {
9402 boolean printed = false;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009403 Iterator<WeakReference<PendingIntentRecord>> it
9404 = mIntentSenderRecords.values().iterator();
9405 while (it.hasNext()) {
9406 WeakReference<PendingIntentRecord> ref = it.next();
9407 PendingIntentRecord rec = ref != null ? ref.get(): null;
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009408 if (dumpPackage != null && (rec == null
9409 || !dumpPackage.equals(rec.key.packageName))) {
9410 continue;
9411 }
9412 if (!printed) {
9413 pw.println("ACTIVITY MANAGER PENDING INTENTS (dumpsys activity intents)");
9414 printed = true;
9415 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009416 needSep = true;
9417 if (rec != null) {
9418 pw.print(" * "); pw.println(rec);
9419 if (dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009420 rec.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009421 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009422 } else {
9423 pw.print(" * "); pw.println(ref);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009424 }
9425 }
9426 }
Dianne Hackbornc59411b2009-12-21 20:10:14 -08009427
9428 return needSep;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009429 }
9430
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009431 private static final void dumpHistoryList(FileDescriptor fd, PrintWriter pw, List list,
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009432 String prefix, String label, boolean complete, boolean brief, boolean client,
9433 String dumpPackage) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009434 TaskRecord lastTask = null;
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009435 boolean needNL = false;
9436 final String innerPrefix = prefix + " ";
9437 final String[] args = new String[0];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009438 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009439 final ActivityRecord r = (ActivityRecord)list.get(i);
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009440 if (dumpPackage != null && !dumpPackage.equals(r.packageName)) {
9441 continue;
9442 }
Dianne Hackbornf26fd992011-04-08 18:14:09 -07009443 final boolean full = !brief && (complete || !r.isInHistory());
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009444 if (needNL) {
9445 pw.println(" ");
9446 needNL = false;
9447 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009448 if (lastTask != r.task) {
9449 lastTask = r.task;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009450 pw.print(prefix);
9451 pw.print(full ? "* " : " ");
9452 pw.println(lastTask);
9453 if (full) {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009454 lastTask.dump(pw, prefix + " ");
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009455 } else if (complete) {
9456 // Complete + brief == give a summary. Isn't that obvious?!?
9457 if (lastTask.intent != null) {
Dianne Hackborn90c52de2011-09-23 12:57:44 -07009458 pw.print(prefix); pw.print(" ");
9459 pw.println(lastTask.intent.toInsecureString());
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009460 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009461 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009462 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009463 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label);
9464 pw.print(" #"); pw.print(i); pw.print(": ");
9465 pw.println(r);
9466 if (full) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009467 r.dump(pw, innerPrefix);
9468 } else if (complete) {
9469 // Complete + brief == give a summary. Isn't that obvious?!?
Dianne Hackborn90c52de2011-09-23 12:57:44 -07009470 pw.print(innerPrefix); pw.println(r.intent.toInsecureString());
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009471 if (r.app != null) {
9472 pw.print(innerPrefix); pw.println(r.app);
9473 }
9474 }
9475 if (client && r.app != null && r.app.thread != null) {
9476 // flush anything that is already in the PrintWriter since the thread is going
9477 // to write to the file descriptor directly
9478 pw.flush();
9479 try {
9480 TransferPipe tp = new TransferPipe();
9481 try {
Dianne Hackbornbe707852011-11-11 14:32:10 -08009482 r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(),
9483 r.appToken, innerPrefix, args);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009484 // Short timeout, since blocking here can
9485 // deadlock with the application.
9486 tp.go(fd, 2000);
9487 } finally {
9488 tp.kill();
9489 }
9490 } catch (IOException e) {
9491 pw.println(innerPrefix + "Failure while dumping the activity: " + e);
9492 } catch (RemoteException e) {
9493 pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
9494 }
9495 needNL = true;
Dianne Hackbornf210d6b2009-04-13 18:42:49 -07009496 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009497 }
9498 }
9499
Dianne Hackborn09c916b2009-12-08 14:50:51 -08009500 private static String buildOomTag(String prefix, String space, int val, int base) {
9501 if (val == base) {
9502 if (space == null) return prefix;
9503 return prefix + " ";
9504 }
9505 return prefix + "+" + Integer.toString(val-base);
9506 }
9507
9508 private static final int dumpProcessList(PrintWriter pw,
9509 ActivityManagerService service, List list,
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009510 String prefix, String normalLabel, String persistentLabel,
9511 String dumpPackage) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009512 int numPers = 0;
Dianne Hackborn32907cf2010-06-10 17:50:20 -07009513 final int N = list.size()-1;
9514 for (int i=N; i>=0; i--) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009515 ProcessRecord r = (ProcessRecord)list.get(i);
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009516 if (dumpPackage != null && !dumpPackage.equals(r.info.packageName)) {
9517 continue;
9518 }
Dianne Hackborn287952c2010-09-22 22:34:31 -07009519 pw.println(String.format("%s%s #%2d: %s",
9520 prefix, (r.persistent ? persistentLabel : normalLabel),
9521 i, r.toString()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009522 if (r.persistent) {
9523 numPers++;
9524 }
9525 }
9526 return numPers;
9527 }
9528
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009529 private static final boolean dumpProcessOomList(PrintWriter pw,
Dianne Hackborn905577f2011-09-07 18:31:28 -07009530 ActivityManagerService service, List<ProcessRecord> origList,
Dianne Hackborn287952c2010-09-22 22:34:31 -07009531 String prefix, String normalLabel, String persistentLabel,
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009532 boolean inclDetails, String dumpPackage) {
Dianne Hackborn287952c2010-09-22 22:34:31 -07009533
Dianne Hackborn905577f2011-09-07 18:31:28 -07009534 ArrayList<Pair<ProcessRecord, Integer>> list
9535 = new ArrayList<Pair<ProcessRecord, Integer>>(origList.size());
9536 for (int i=0; i<origList.size(); i++) {
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009537 ProcessRecord r = origList.get(i);
9538 if (dumpPackage != null && !dumpPackage.equals(r.info.packageName)) {
9539 continue;
9540 }
Dianne Hackborn905577f2011-09-07 18:31:28 -07009541 list.add(new Pair<ProcessRecord, Integer>(origList.get(i), i));
9542 }
9543
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009544 if (list.size() <= 0) {
9545 return false;
9546 }
9547
Dianne Hackborn905577f2011-09-07 18:31:28 -07009548 Comparator<Pair<ProcessRecord, Integer>> comparator
9549 = new Comparator<Pair<ProcessRecord, Integer>>() {
9550 @Override
9551 public int compare(Pair<ProcessRecord, Integer> object1,
9552 Pair<ProcessRecord, Integer> object2) {
9553 if (object1.first.setAdj != object2.first.setAdj) {
9554 return object1.first.setAdj > object2.first.setAdj ? -1 : 1;
9555 }
9556 if (object1.second.intValue() != object2.second.intValue()) {
9557 return object1.second.intValue() > object2.second.intValue() ? -1 : 1;
9558 }
9559 return 0;
9560 }
9561 };
9562
9563 Collections.sort(list, comparator);
9564
Dianne Hackborn287952c2010-09-22 22:34:31 -07009565 final long curRealtime = SystemClock.elapsedRealtime();
9566 final long realtimeSince = curRealtime - service.mLastPowerCheckRealtime;
9567 final long curUptime = SystemClock.uptimeMillis();
9568 final long uptimeSince = curUptime - service.mLastPowerCheckUptime;
9569
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009570 for (int i=list.size()-1; i>=0; i--) {
Dianne Hackborn905577f2011-09-07 18:31:28 -07009571 ProcessRecord r = list.get(i).first;
Dianne Hackborn287952c2010-09-22 22:34:31 -07009572 String oomAdj;
Dianne Hackborne02c88a2011-10-28 13:58:15 -07009573 if (r.setAdj >= ProcessList.HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn7d608422011-08-07 16:24:18 -07009574 oomAdj = buildOomTag("bak", " ", r.setAdj, ProcessList.HIDDEN_APP_MIN_ADJ);
Dianne Hackborne02c88a2011-10-28 13:58:15 -07009575 } else if (r.setAdj >= ProcessList.SERVICE_B_ADJ) {
9576 oomAdj = buildOomTag("svcb ", null, r.setAdj, ProcessList.SERVICE_B_ADJ);
Dianne Hackbornf35fe232011-11-01 19:25:20 -07009577 } else if (r.setAdj >= ProcessList.PREVIOUS_APP_ADJ) {
9578 oomAdj = buildOomTag("prev ", null, r.setAdj, ProcessList.PREVIOUS_APP_ADJ);
Dianne Hackborn7d608422011-08-07 16:24:18 -07009579 } else if (r.setAdj >= ProcessList.HOME_APP_ADJ) {
9580 oomAdj = buildOomTag("home ", null, r.setAdj, ProcessList.HOME_APP_ADJ);
Dianne Hackborne02c88a2011-10-28 13:58:15 -07009581 } else if (r.setAdj >= ProcessList.SERVICE_ADJ) {
9582 oomAdj = buildOomTag("svc ", null, r.setAdj, ProcessList.SERVICE_ADJ);
Dianne Hackborn7d608422011-08-07 16:24:18 -07009583 } else if (r.setAdj >= ProcessList.BACKUP_APP_ADJ) {
Dianne Hackborn672342c2011-11-29 11:29:02 -08009584 oomAdj = buildOomTag("bkup ", null, r.setAdj, ProcessList.BACKUP_APP_ADJ);
Dianne Hackborn7d608422011-08-07 16:24:18 -07009585 } else if (r.setAdj >= ProcessList.HEAVY_WEIGHT_APP_ADJ) {
9586 oomAdj = buildOomTag("hvy ", null, r.setAdj, ProcessList.HEAVY_WEIGHT_APP_ADJ);
9587 } else if (r.setAdj >= ProcessList.PERCEPTIBLE_APP_ADJ) {
9588 oomAdj = buildOomTag("prcp ", null, r.setAdj, ProcessList.PERCEPTIBLE_APP_ADJ);
9589 } else if (r.setAdj >= ProcessList.VISIBLE_APP_ADJ) {
9590 oomAdj = buildOomTag("vis ", null, r.setAdj, ProcessList.VISIBLE_APP_ADJ);
9591 } else if (r.setAdj >= ProcessList.FOREGROUND_APP_ADJ) {
9592 oomAdj = buildOomTag("fore ", null, r.setAdj, ProcessList.FOREGROUND_APP_ADJ);
Dianne Hackborne02c88a2011-10-28 13:58:15 -07009593 } else if (r.setAdj >= ProcessList.PERSISTENT_PROC_ADJ) {
9594 oomAdj = buildOomTag("pers ", null, r.setAdj, ProcessList.PERSISTENT_PROC_ADJ);
Dianne Hackborn7d608422011-08-07 16:24:18 -07009595 } else if (r.setAdj >= ProcessList.SYSTEM_ADJ) {
9596 oomAdj = buildOomTag("sys ", null, r.setAdj, ProcessList.SYSTEM_ADJ);
Dianne Hackborn287952c2010-09-22 22:34:31 -07009597 } else {
9598 oomAdj = Integer.toString(r.setAdj);
9599 }
9600 String schedGroup;
9601 switch (r.setSchedGroup) {
9602 case Process.THREAD_GROUP_BG_NONINTERACTIVE:
9603 schedGroup = "B";
9604 break;
9605 case Process.THREAD_GROUP_DEFAULT:
9606 schedGroup = "F";
9607 break;
9608 default:
9609 schedGroup = Integer.toString(r.setSchedGroup);
9610 break;
9611 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -07009612 String foreground;
9613 if (r.foregroundActivities) {
9614 foreground = "A";
9615 } else if (r.foregroundServices) {
9616 foreground = "S";
9617 } else {
9618 foreground = " ";
9619 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -07009620 pw.println(String.format("%s%s #%2d: adj=%s/%s%s trm=%2d %s (%s)",
Dianne Hackborn287952c2010-09-22 22:34:31 -07009621 prefix, (r.persistent ? persistentLabel : normalLabel),
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009622 (origList.size()-1)-list.get(i).second, oomAdj, schedGroup,
9623 foreground, r.trimMemoryLevel, r.toShortString(), r.adjType));
Dianne Hackborn287952c2010-09-22 22:34:31 -07009624 if (r.adjSource != null || r.adjTarget != null) {
9625 pw.print(prefix);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009626 pw.print(" ");
Dianne Hackborn287952c2010-09-22 22:34:31 -07009627 if (r.adjTarget instanceof ComponentName) {
9628 pw.print(((ComponentName)r.adjTarget).flattenToShortString());
9629 } else if (r.adjTarget != null) {
9630 pw.print(r.adjTarget.toString());
9631 } else {
9632 pw.print("{null}");
9633 }
9634 pw.print("<=");
9635 if (r.adjSource instanceof ProcessRecord) {
9636 pw.print("Proc{");
9637 pw.print(((ProcessRecord)r.adjSource).toShortString());
9638 pw.println("}");
9639 } else if (r.adjSource != null) {
9640 pw.println(r.adjSource.toString());
9641 } else {
9642 pw.println("{null}");
9643 }
9644 }
9645 if (inclDetails) {
9646 pw.print(prefix);
9647 pw.print(" ");
9648 pw.print("oom: max="); pw.print(r.maxAdj);
9649 pw.print(" hidden="); pw.print(r.hiddenAdj);
9650 pw.print(" curRaw="); pw.print(r.curRawAdj);
9651 pw.print(" setRaw="); pw.print(r.setRawAdj);
9652 pw.print(" cur="); pw.print(r.curAdj);
9653 pw.print(" set="); pw.println(r.setAdj);
9654 pw.print(prefix);
9655 pw.print(" ");
9656 pw.print("keeping="); pw.print(r.keeping);
9657 pw.print(" hidden="); pw.print(r.hidden);
Dianne Hackbornc68c9132011-07-29 01:25:18 -07009658 pw.print(" empty="); pw.print(r.empty);
9659 pw.print(" hasAboveClient="); pw.println(r.hasAboveClient);
Dianne Hackborn287952c2010-09-22 22:34:31 -07009660
9661 if (!r.keeping) {
9662 if (r.lastWakeTime != 0) {
9663 long wtime;
9664 BatteryStatsImpl stats = service.mBatteryStatsService.getActiveStatistics();
9665 synchronized (stats) {
9666 wtime = stats.getProcessWakeTime(r.info.uid,
9667 r.pid, curRealtime);
9668 }
9669 long timeUsed = wtime - r.lastWakeTime;
9670 pw.print(prefix);
9671 pw.print(" ");
9672 pw.print("keep awake over ");
9673 TimeUtils.formatDuration(realtimeSince, pw);
9674 pw.print(" used ");
9675 TimeUtils.formatDuration(timeUsed, pw);
9676 pw.print(" (");
9677 pw.print((timeUsed*100)/realtimeSince);
9678 pw.println("%)");
9679 }
9680 if (r.lastCpuTime != 0) {
9681 long timeUsed = r.curCpuTime - r.lastCpuTime;
9682 pw.print(prefix);
9683 pw.print(" ");
9684 pw.print("run cpu over ");
9685 TimeUtils.formatDuration(uptimeSince, pw);
9686 pw.print(" used ");
9687 TimeUtils.formatDuration(timeUsed, pw);
9688 pw.print(" (");
9689 pw.print((timeUsed*100)/uptimeSince);
9690 pw.println("%)");
9691 }
9692 }
9693 }
9694 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08009695 return true;
Dianne Hackborn287952c2010-09-22 22:34:31 -07009696 }
9697
Dianne Hackbornb437e092011-08-05 17:50:29 -07009698 ArrayList<ProcessRecord> collectProcesses(PrintWriter pw, int start, String[] args) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009699 ArrayList<ProcessRecord> procs;
9700 synchronized (this) {
Dianne Hackbornb437e092011-08-05 17:50:29 -07009701 if (args != null && args.length > start
9702 && args[start].charAt(0) != '-') {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009703 procs = new ArrayList<ProcessRecord>();
9704 int pid = -1;
9705 try {
Dianne Hackbornb437e092011-08-05 17:50:29 -07009706 pid = Integer.parseInt(args[start]);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009707 } catch (NumberFormatException e) {
9708
9709 }
9710 for (int i=mLruProcesses.size()-1; i>=0; i--) {
9711 ProcessRecord proc = mLruProcesses.get(i);
9712 if (proc.pid == pid) {
9713 procs.add(proc);
Dianne Hackbornb437e092011-08-05 17:50:29 -07009714 } else if (proc.processName.equals(args[start])) {
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009715 procs.add(proc);
9716 }
9717 }
9718 if (procs.size() <= 0) {
Dianne Hackbornb437e092011-08-05 17:50:29 -07009719 pw.println("No process found for: " + args[start]);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009720 return null;
9721 }
9722 } else {
9723 procs = new ArrayList<ProcessRecord>(mLruProcesses);
9724 }
9725 }
9726 return procs;
9727 }
9728
9729 final void dumpGraphicsHardwareUsage(FileDescriptor fd,
9730 PrintWriter pw, String[] args) {
Dianne Hackbornb437e092011-08-05 17:50:29 -07009731 ArrayList<ProcessRecord> procs = collectProcesses(pw, 0, args);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009732 if (procs == null) {
9733 return;
9734 }
9735
9736 long uptime = SystemClock.uptimeMillis();
9737 long realtime = SystemClock.elapsedRealtime();
9738 pw.println("Applications Graphics Acceleration Info:");
9739 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
9740
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009741 for (int i = procs.size() - 1 ; i >= 0 ; i--) {
9742 ProcessRecord r = procs.get(i);
Chet Haase9c1e23b2011-03-24 10:51:31 -07009743 if (r.thread != null) {
9744 pw.println("\n** Graphics info for pid " + r.pid + " [" + r.processName + "] **");
9745 pw.flush();
9746 try {
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009747 TransferPipe tp = new TransferPipe();
9748 try {
9749 r.thread.dumpGfxInfo(tp.getWriteFd().getFileDescriptor(), args);
9750 tp.go(fd);
9751 } finally {
9752 tp.kill();
9753 }
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009754 } catch (IOException e) {
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009755 pw.println("Failure while dumping the app: " + r);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009756 pw.flush();
Chet Haase9c1e23b2011-03-24 10:51:31 -07009757 } catch (RemoteException e) {
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009758 pw.println("Got a RemoteException while dumping the app " + r);
Chet Haase9c1e23b2011-03-24 10:51:31 -07009759 pw.flush();
9760 }
9761 }
9762 }
Chet Haase9c1e23b2011-03-24 10:51:31 -07009763 }
9764
Jeff Brown6754ba22011-12-14 20:20:01 -08009765 final void dumpDbInfo(FileDescriptor fd, PrintWriter pw, String[] args) {
9766 ArrayList<ProcessRecord> procs = collectProcesses(pw, 0, args);
9767 if (procs == null) {
9768 return;
9769 }
9770
9771 pw.println("Applications Database Info:");
9772
9773 for (int i = procs.size() - 1 ; i >= 0 ; i--) {
9774 ProcessRecord r = procs.get(i);
9775 if (r.thread != null) {
9776 pw.println("\n** Database info for pid " + r.pid + " [" + r.processName + "] **");
9777 pw.flush();
9778 try {
9779 TransferPipe tp = new TransferPipe();
9780 try {
9781 r.thread.dumpDbInfo(tp.getWriteFd().getFileDescriptor(), args);
9782 tp.go(fd);
9783 } finally {
9784 tp.kill();
9785 }
9786 } catch (IOException e) {
9787 pw.println("Failure while dumping the app: " + r);
9788 pw.flush();
9789 } catch (RemoteException e) {
9790 pw.println("Got a RemoteException while dumping the app " + r);
9791 pw.flush();
9792 }
9793 }
9794 }
9795 }
9796
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009797 final static class MemItem {
9798 final String label;
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -08009799 final String shortLabel;
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009800 final long pss;
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -08009801 final int id;
Dianne Hackborna4bacb82011-08-24 15:12:38 -07009802 ArrayList<MemItem> subitems;
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009803
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -08009804 public MemItem(String _label, String _shortLabel, long _pss, int _id) {
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009805 label = _label;
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -08009806 shortLabel = _shortLabel;
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009807 pss = _pss;
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -08009808 id = _id;
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009809 }
9810 }
9811
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -08009812 static final void dumpMemItems(PrintWriter pw, String prefix, ArrayList<MemItem> items,
Dianne Hackbornb437e092011-08-05 17:50:29 -07009813 boolean sort) {
9814 if (sort) {
9815 Collections.sort(items, new Comparator<MemItem>() {
9816 @Override
9817 public int compare(MemItem lhs, MemItem rhs) {
9818 if (lhs.pss < rhs.pss) {
9819 return 1;
9820 } else if (lhs.pss > rhs.pss) {
9821 return -1;
9822 }
9823 return 0;
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009824 }
Dianne Hackbornb437e092011-08-05 17:50:29 -07009825 });
9826 }
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009827
9828 for (int i=0; i<items.size(); i++) {
9829 MemItem mi = items.get(i);
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -08009830 pw.print(prefix); pw.printf("%7d kB: ", mi.pss); pw.println(mi.label);
Dianne Hackborna4bacb82011-08-24 15:12:38 -07009831 if (mi.subitems != null) {
9832 dumpMemItems(pw, prefix + " ", mi.subitems, true);
9833 }
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009834 }
9835 }
9836
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -08009837 // These are in KB.
9838 static final long[] DUMP_MEM_BUCKETS = new long[] {
9839 5*1024, 7*1024, 10*1024, 15*1024, 20*1024, 30*1024, 40*1024, 80*1024,
9840 120*1024, 160*1024, 200*1024,
9841 250*1024, 300*1024, 350*1024, 400*1024, 500*1024, 600*1024, 800*1024,
9842 1*1024*1024, 2*1024*1024, 5*1024*1024, 10*1024*1024, 20*1024*1024
9843 };
9844
Dianne Hackborn672342c2011-11-29 11:29:02 -08009845 static final void appendMemBucket(StringBuilder out, long memKB, String label,
9846 boolean stackLike) {
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -08009847 int start = label.lastIndexOf('.');
9848 if (start >= 0) start++;
9849 else start = 0;
9850 int end = label.length();
9851 for (int i=0; i<DUMP_MEM_BUCKETS.length; i++) {
9852 if (DUMP_MEM_BUCKETS[i] >= memKB) {
9853 long bucket = DUMP_MEM_BUCKETS[i]/1024;
9854 out.append(bucket);
Dianne Hackborn672342c2011-11-29 11:29:02 -08009855 out.append(stackLike ? "MB." : "MB ");
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -08009856 out.append(label, start, end);
9857 return;
9858 }
9859 }
9860 out.append(memKB/1024);
Dianne Hackborn672342c2011-11-29 11:29:02 -08009861 out.append(stackLike ? "MB." : "MB ");
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -08009862 out.append(label, start, end);
9863 }
9864
9865 static final int[] DUMP_MEM_OOM_ADJ = new int[] {
9866 ProcessList.SYSTEM_ADJ, ProcessList.PERSISTENT_PROC_ADJ, ProcessList.FOREGROUND_APP_ADJ,
9867 ProcessList.VISIBLE_APP_ADJ, ProcessList.PERCEPTIBLE_APP_ADJ, ProcessList.HEAVY_WEIGHT_APP_ADJ,
9868 ProcessList.BACKUP_APP_ADJ, ProcessList.SERVICE_ADJ, ProcessList.HOME_APP_ADJ,
9869 ProcessList.PREVIOUS_APP_ADJ, ProcessList.SERVICE_B_ADJ, ProcessList.HIDDEN_APP_MAX_ADJ
9870 };
9871 static final String[] DUMP_MEM_OOM_LABEL = new String[] {
9872 "System", "Persistent", "Foreground",
9873 "Visible", "Perceptible", "Heavy Weight",
9874 "Backup", "A Services", "Home", "Previous",
9875 "B Services", "Background"
9876 };
9877
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009878 final void dumpApplicationMemoryUsage(FileDescriptor fd,
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08009879 PrintWriter pw, String prefix, String[] args, boolean brief,
Dianne Hackborn672342c2011-11-29 11:29:02 -08009880 PrintWriter categoryPw, StringBuilder outTag, StringBuilder outStack) {
Dianne Hackbornb437e092011-08-05 17:50:29 -07009881 boolean dumpAll = false;
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08009882 boolean oomOnly = false;
Dianne Hackbornb437e092011-08-05 17:50:29 -07009883
9884 int opti = 0;
9885 while (opti < args.length) {
9886 String opt = args[opti];
9887 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
9888 break;
9889 }
9890 opti++;
9891 if ("-a".equals(opt)) {
9892 dumpAll = true;
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08009893 } else if ("--oom".equals(opt)) {
9894 oomOnly = true;
Dianne Hackbornb437e092011-08-05 17:50:29 -07009895 } else if ("-h".equals(opt)) {
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08009896 pw.println("meminfo dump options: [-a] [--oom] [process]");
Dianne Hackbornb437e092011-08-05 17:50:29 -07009897 pw.println(" -a: include all available information for each process.");
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -08009898 pw.println(" --oom: only show processes organized by oom adj.");
Dianne Hackbornb437e092011-08-05 17:50:29 -07009899 pw.println("If [process] is specified it can be the name or ");
9900 pw.println("pid of a specific process to dump.");
9901 return;
9902 } else {
9903 pw.println("Unknown argument: " + opt + "; use -h for help");
9904 }
9905 }
9906
9907 ArrayList<ProcessRecord> procs = collectProcesses(pw, opti, args);
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009908 if (procs == null) {
9909 return;
9910 }
9911
Dianne Hackborn6447ca32009-04-07 19:50:08 -07009912 final boolean isCheckinRequest = scanArgs(args, "--checkin");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009913 long uptime = SystemClock.uptimeMillis();
9914 long realtime = SystemClock.elapsedRealtime();
Dianne Hackbornb437e092011-08-05 17:50:29 -07009915
9916 if (procs.size() == 1 || isCheckinRequest) {
9917 dumpAll = true;
9918 }
9919
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009920 if (isCheckinRequest) {
9921 // short checkin version
9922 pw.println(uptime + "," + realtime);
9923 pw.flush();
9924 } else {
9925 pw.println("Applications Memory Usage (kB):");
9926 pw.println("Uptime: " + uptime + " Realtime: " + realtime);
9927 }
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009928
Dianne Hackbornb437e092011-08-05 17:50:29 -07009929 String[] innerArgs = new String[args.length-opti];
9930 System.arraycopy(args, opti, innerArgs, 0, args.length-opti);
9931
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009932 ArrayList<MemItem> procMems = new ArrayList<MemItem>();
9933 long nativePss=0, dalvikPss=0, otherPss=0;
9934 long[] miscPss = new long[Debug.MemoryInfo.NUM_OTHER_STATS];
9935
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -08009936 long oomPss[] = new long[DUMP_MEM_OOM_LABEL.length];
9937 ArrayList<MemItem>[] oomProcs = (ArrayList<MemItem>[])
9938 new ArrayList[DUMP_MEM_OOM_LABEL.length];
Dianne Hackbornb437e092011-08-05 17:50:29 -07009939
9940 long totalPss = 0;
9941
Dianne Hackborne17aeb32011-04-07 15:11:57 -07009942 for (int i = procs.size() - 1 ; i >= 0 ; i--) {
9943 ProcessRecord r = procs.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009944 if (r.thread != null) {
Dianne Hackbornb437e092011-08-05 17:50:29 -07009945 if (!isCheckinRequest && dumpAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009946 pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");
9947 pw.flush();
9948 }
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009949 Debug.MemoryInfo mi = null;
Dianne Hackbornb437e092011-08-05 17:50:29 -07009950 if (dumpAll) {
9951 try {
9952 mi = r.thread.dumpMemInfo(fd, isCheckinRequest, dumpAll, innerArgs);
9953 } catch (RemoteException e) {
9954 if (!isCheckinRequest) {
9955 pw.println("Got RemoteException!");
9956 pw.flush();
9957 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009958 }
Dianne Hackbornb437e092011-08-05 17:50:29 -07009959 } else {
9960 mi = new Debug.MemoryInfo();
9961 Debug.getMemoryInfo(r.pid, mi);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009962 }
Dianne Hackbornb437e092011-08-05 17:50:29 -07009963
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009964 if (!isCheckinRequest && mi != null) {
Dianne Hackbornb437e092011-08-05 17:50:29 -07009965 long myTotalPss = mi.getTotalPss();
9966 totalPss += myTotalPss;
Dianne Hackborna4bacb82011-08-24 15:12:38 -07009967 MemItem pssItem = new MemItem(r.processName + " (pid " + r.pid + ")",
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -08009968 r.processName, myTotalPss, 0);
Dianne Hackborna4bacb82011-08-24 15:12:38 -07009969 procMems.add(pssItem);
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009970
9971 nativePss += mi.nativePss;
9972 dalvikPss += mi.dalvikPss;
9973 otherPss += mi.otherPss;
9974 for (int j=0; j<Debug.MemoryInfo.NUM_OTHER_STATS; j++) {
9975 long mem = mi.getOtherPss(j);
9976 miscPss[j] += mem;
9977 otherPss -= mem;
9978 }
Dianne Hackbornb437e092011-08-05 17:50:29 -07009979
9980 for (int oomIndex=0; oomIndex<oomPss.length; oomIndex++) {
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -08009981 if (r.setAdj <= DUMP_MEM_OOM_ADJ[oomIndex]
9982 || oomIndex == (oomPss.length-1)) {
Dianne Hackbornb437e092011-08-05 17:50:29 -07009983 oomPss[oomIndex] += myTotalPss;
Dianne Hackborna4bacb82011-08-24 15:12:38 -07009984 if (oomProcs[oomIndex] == null) {
9985 oomProcs[oomIndex] = new ArrayList<MemItem>();
9986 }
9987 oomProcs[oomIndex].add(pssItem);
Dianne Hackbornb437e092011-08-05 17:50:29 -07009988 break;
9989 }
9990 }
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009991 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009992 }
9993 }
Dianne Hackborn0e3328f2011-07-17 13:31:17 -07009994
9995 if (!isCheckinRequest && procs.size() > 1) {
9996 ArrayList<MemItem> catMems = new ArrayList<MemItem>();
9997
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -08009998 catMems.add(new MemItem("Native", "Native", nativePss, -1));
9999 catMems.add(new MemItem("Dalvik", "Dalvik", dalvikPss, -2));
10000 catMems.add(new MemItem("Unknown", "Unknown", otherPss, -3));
Dianne Hackborn0e3328f2011-07-17 13:31:17 -070010001 for (int j=0; j<Debug.MemoryInfo.NUM_OTHER_STATS; j++) {
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010002 String label = Debug.MemoryInfo.getOtherLabel(j);
10003 catMems.add(new MemItem(label, label, miscPss[j], j));
Dianne Hackborn0e3328f2011-07-17 13:31:17 -070010004 }
10005
Dianne Hackbornb437e092011-08-05 17:50:29 -070010006 ArrayList<MemItem> oomMems = new ArrayList<MemItem>();
10007 for (int j=0; j<oomPss.length; j++) {
10008 if (oomPss[j] != 0) {
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010009 String label = DUMP_MEM_OOM_LABEL[j];
10010 MemItem item = new MemItem(label, label, oomPss[j],
10011 DUMP_MEM_OOM_ADJ[j]);
Dianne Hackborna4bacb82011-08-24 15:12:38 -070010012 item.subitems = oomProcs[j];
10013 oomMems.add(item);
Dianne Hackbornb437e092011-08-05 17:50:29 -070010014 }
10015 }
10016
Dianne Hackborn672342c2011-11-29 11:29:02 -080010017 if (outTag != null || outStack != null) {
10018 if (outTag != null) {
10019 appendMemBucket(outTag, totalPss, "total", false);
10020 }
10021 if (outStack != null) {
10022 appendMemBucket(outStack, totalPss, "total", true);
10023 }
10024 boolean firstLine = true;
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010025 for (int i=0; i<oomMems.size(); i++) {
10026 MemItem miCat = oomMems.get(i);
10027 if (miCat.subitems == null || miCat.subitems.size() < 1) {
10028 continue;
10029 }
10030 if (miCat.id < ProcessList.SERVICE_ADJ
10031 || miCat.id == ProcessList.HOME_APP_ADJ
10032 || miCat.id == ProcessList.PREVIOUS_APP_ADJ) {
Dianne Hackborn672342c2011-11-29 11:29:02 -080010033 if (outTag != null && miCat.id <= ProcessList.FOREGROUND_APP_ADJ) {
10034 outTag.append(" / ");
10035 }
10036 if (outStack != null) {
10037 if (miCat.id >= ProcessList.FOREGROUND_APP_ADJ) {
10038 if (firstLine) {
10039 outStack.append(":");
10040 firstLine = false;
10041 }
10042 outStack.append("\n\t at ");
10043 } else {
10044 outStack.append("$");
10045 }
10046 }
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010047 for (int j=0; j<miCat.subitems.size(); j++) {
10048 MemItem mi = miCat.subitems.get(j);
10049 if (j > 0) {
Dianne Hackborn672342c2011-11-29 11:29:02 -080010050 if (outTag != null) {
10051 outTag.append(" ");
10052 }
10053 if (outStack != null) {
10054 outStack.append("$");
10055 }
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010056 }
Dianne Hackborn672342c2011-11-29 11:29:02 -080010057 if (outTag != null && miCat.id <= ProcessList.FOREGROUND_APP_ADJ) {
10058 appendMemBucket(outTag, mi.pss, mi.shortLabel, false);
10059 }
10060 if (outStack != null) {
10061 appendMemBucket(outStack, mi.pss, mi.shortLabel, true);
10062 }
10063 }
10064 if (outStack != null && miCat.id >= ProcessList.FOREGROUND_APP_ADJ) {
10065 outStack.append("(");
10066 for (int k=0; k<DUMP_MEM_OOM_ADJ.length; k++) {
10067 if (DUMP_MEM_OOM_ADJ[k] == miCat.id) {
10068 outStack.append(DUMP_MEM_OOM_LABEL[k]);
10069 outStack.append(":");
10070 outStack.append(DUMP_MEM_OOM_ADJ[k]);
10071 }
10072 }
10073 outStack.append(")");
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010074 }
10075 }
10076 }
10077 }
10078
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -080010079 if (!brief && !oomOnly) {
Dianne Hackborn04d6db32011-11-04 20:07:24 -070010080 pw.println();
10081 pw.println("Total PSS by process:");
10082 dumpMemItems(pw, " ", procMems, true);
10083 pw.println();
10084 }
Dianne Hackbornb437e092011-08-05 17:50:29 -070010085 pw.println("Total PSS by OOM adjustment:");
10086 dumpMemItems(pw, " ", oomMems, false);
Dianne Hackborne4d4fbc2011-11-08 11:53:28 -080010087 if (!oomOnly) {
10088 PrintWriter out = categoryPw != null ? categoryPw : pw;
10089 out.println();
10090 out.println("Total PSS by category:");
10091 dumpMemItems(out, " ", catMems, true);
Dianne Hackborn04d6db32011-11-04 20:07:24 -070010092 }
Dianne Hackbornb437e092011-08-05 17:50:29 -070010093 pw.println();
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080010094 pw.print("Total PSS: "); pw.print(totalPss); pw.println(" kB");
Dianne Hackborn0e3328f2011-07-17 13:31:17 -070010095 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010096 }
10097
10098 /**
10099 * Searches array of arguments for the specified string
10100 * @param args array of argument strings
10101 * @param value value to search for
10102 * @return true if the value is contained in the array
10103 */
10104 private static boolean scanArgs(String[] args, String value) {
10105 if (args != null) {
10106 for (String arg : args) {
10107 if (value.equals(arg)) {
10108 return true;
10109 }
10110 }
10111 }
10112 return false;
10113 }
10114
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010115 private final void killServicesLocked(ProcessRecord app,
10116 boolean allowRestart) {
10117 // Report disconnected services.
10118 if (false) {
10119 // XXX we are letting the client link to the service for
10120 // death notifications.
10121 if (app.services.size() > 0) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010122 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010123 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010124 ServiceRecord r = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010125 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010126 Iterator<ArrayList<ConnectionRecord>> jt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010127 = r.connections.values().iterator();
10128 while (jt.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010129 ArrayList<ConnectionRecord> cl = jt.next();
10130 for (int i=0; i<cl.size(); i++) {
10131 ConnectionRecord c = cl.get(i);
10132 if (c.binding.client != app) {
10133 try {
10134 //c.conn.connected(r.className, null);
10135 } catch (Exception e) {
10136 // todo: this should be asynchronous!
10137 Slog.w(TAG, "Exception thrown disconnected servce "
10138 + r.shortName
10139 + " from app " + app.processName, e);
10140 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010141 }
10142 }
10143 }
10144 }
10145 }
10146 }
10147 }
10148
10149 // Clean up any connections this application has to other services.
10150 if (app.connections.size() > 0) {
10151 Iterator<ConnectionRecord> it = app.connections.iterator();
10152 while (it.hasNext()) {
10153 ConnectionRecord r = it.next();
10154 removeConnectionLocked(r, app, null);
10155 }
10156 }
10157 app.connections.clear();
10158
10159 if (app.services.size() != 0) {
10160 // Any services running in the application need to be placed
10161 // back in the pending list.
Dianne Hackborn860755f2010-06-03 18:47:52 -070010162 Iterator<ServiceRecord> it = app.services.iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010163 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010164 ServiceRecord sr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010165 synchronized (sr.stats.getBatteryStats()) {
10166 sr.stats.stopLaunchedLocked();
10167 }
10168 sr.app = null;
10169 sr.executeNesting = 0;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010170 if (mStoppingServices.remove(sr)) {
10171 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
10172 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010173
10174 boolean hasClients = sr.bindings.size() > 0;
10175 if (hasClients) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010176 Iterator<IntentBindRecord> bindings
10177 = sr.bindings.values().iterator();
10178 while (bindings.hasNext()) {
10179 IntentBindRecord b = bindings.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010180 if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010181 + ": shouldUnbind=" + b.hasBound);
10182 b.binder = null;
10183 b.requested = b.received = b.hasBound = false;
10184 }
10185 }
10186
Dianne Hackborn070783f2010-12-29 16:46:28 -080010187 if (sr.crashCount >= 2 && (sr.serviceInfo.applicationInfo.flags
10188 &ApplicationInfo.FLAG_PERSISTENT) == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010189 Slog.w(TAG, "Service crashed " + sr.crashCount
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010190 + " times, stopping: " + sr);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010191 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010192 sr.crashCount, sr.shortName, app.pid);
10193 bringDownServiceLocked(sr, true);
10194 } else if (!allowRestart) {
10195 bringDownServiceLocked(sr, true);
10196 } else {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010197 boolean canceled = scheduleServiceRestartLocked(sr, true);
10198
10199 // Should the service remain running? Note that in the
10200 // extreme case of so many attempts to deliver a command
Dianne Hackborn130b0d22011-07-26 22:07:48 -070010201 // that it failed we also will stop it here.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010202 if (sr.startRequested && (sr.stopIfKilled || canceled)) {
10203 if (sr.pendingStarts.size() == 0) {
10204 sr.startRequested = false;
10205 if (!hasClients) {
10206 // Whoops, no reason to restart!
10207 bringDownServiceLocked(sr, true);
10208 }
10209 }
10210 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010211 }
10212 }
10213
10214 if (!allowRestart) {
10215 app.services.clear();
10216 }
10217 }
10218
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010219 // Make sure we have no more records on the stopping list.
10220 int i = mStoppingServices.size();
10221 while (i > 0) {
10222 i--;
10223 ServiceRecord sr = mStoppingServices.get(i);
10224 if (sr.app == app) {
10225 mStoppingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010226 if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010227 }
10228 }
10229
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010230 app.executingServices.clear();
10231 }
10232
10233 private final void removeDyingProviderLocked(ProcessRecord proc,
10234 ContentProviderRecord cpr) {
10235 synchronized (cpr) {
10236 cpr.launchingApp = null;
10237 cpr.notifyAll();
10238 }
10239
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -070010240 mProvidersByClass.remove(cpr.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010241 String names[] = cpr.info.authority.split(";");
10242 for (int j = 0; j < names.length; j++) {
10243 mProvidersByName.remove(names[j]);
10244 }
10245
10246 Iterator<ProcessRecord> cit = cpr.clients.iterator();
10247 while (cit.hasNext()) {
10248 ProcessRecord capp = cit.next();
10249 if (!capp.persistent && capp.thread != null
10250 && capp.pid != 0
10251 && capp.pid != MY_PID) {
Dianne Hackborn8633e682010-04-22 16:03:41 -070010252 Slog.i(TAG, "Kill " + capp.processName
10253 + " (pid " + capp.pid + "): provider " + cpr.info.name
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -070010254 + " in dying process " + (proc != null ? proc.processName : "??"));
Dianne Hackborn8633e682010-04-22 16:03:41 -070010255 EventLog.writeEvent(EventLogTags.AM_KILL, capp.pid,
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -070010256 capp.processName, capp.setAdj, "dying provider "
10257 + cpr.name.toShortString());
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010258 Process.killProcessQuiet(capp.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010259 }
10260 }
10261
10262 mLaunchingProviders.remove(cpr);
10263 }
10264
10265 /**
10266 * Main code for cleaning up a process when it has gone away. This is
10267 * called both as a result of the process dying, or directly when stopping
10268 * a process when running in single process mode.
10269 */
10270 private final void cleanUpApplicationRecordLocked(ProcessRecord app,
Dianne Hackborn130b0d22011-07-26 22:07:48 -070010271 boolean restarting, boolean allowRestart, int index) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010272 if (index >= 0) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010273 mLruProcesses.remove(index);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010274 }
10275
Dianne Hackborn36124872009-10-08 16:22:03 -070010276 mProcessesToGc.remove(app);
10277
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010278 // Dismiss any open dialogs.
10279 if (app.crashDialog != null) {
10280 app.crashDialog.dismiss();
10281 app.crashDialog = null;
10282 }
10283 if (app.anrDialog != null) {
10284 app.anrDialog.dismiss();
10285 app.anrDialog = null;
10286 }
10287 if (app.waitDialog != null) {
10288 app.waitDialog.dismiss();
10289 app.waitDialog = null;
10290 }
10291
10292 app.crashing = false;
10293 app.notResponding = false;
10294
10295 app.resetPackageList();
Dianne Hackborn1b64e0d2011-07-17 15:23:59 -070010296 app.unlinkDeathRecipient();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010297 app.thread = null;
10298 app.forcingToForeground = null;
10299 app.foregroundServices = false;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070010300 app.foregroundActivities = false;
Dianne Hackbornf0754f5b2011-07-21 16:02:07 -070010301 app.hasShownUi = false;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070010302 app.hasAboveClient = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010303
Dianne Hackborn130b0d22011-07-26 22:07:48 -070010304 killServicesLocked(app, allowRestart);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010305
10306 boolean restart = false;
10307
10308 int NL = mLaunchingProviders.size();
10309
10310 // Remove published content providers.
10311 if (!app.pubProviders.isEmpty()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010312 Iterator<ContentProviderRecord> it = app.pubProviders.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010313 while (it.hasNext()) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010314 ContentProviderRecord cpr = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010315 cpr.provider = null;
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -070010316 cpr.proc = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010317
10318 // See if someone is waiting for this provider... in which
10319 // case we don't remove it, but just let it restart.
10320 int i = 0;
Dianne Hackborn130b0d22011-07-26 22:07:48 -070010321 if (!app.bad && allowRestart) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010322 for (; i<NL; i++) {
10323 if (mLaunchingProviders.get(i) == cpr) {
10324 restart = true;
10325 break;
10326 }
10327 }
10328 } else {
10329 i = NL;
10330 }
10331
10332 if (i >= NL) {
10333 removeDyingProviderLocked(app, cpr);
10334 NL = mLaunchingProviders.size();
10335 }
10336 }
10337 app.pubProviders.clear();
10338 }
10339
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010340 // Take care of any launching providers waiting for this process.
10341 if (checkAppInLaunchingProvidersLocked(app, false)) {
10342 restart = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010343 }
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010344
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010345 // Unregister from connected content providers.
10346 if (!app.conProviders.isEmpty()) {
Dianne Hackborn0c3154d2009-10-06 17:18:05 -070010347 Iterator it = app.conProviders.keySet().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010348 while (it.hasNext()) {
10349 ContentProviderRecord cpr = (ContentProviderRecord)it.next();
10350 cpr.clients.remove(app);
10351 }
10352 app.conProviders.clear();
10353 }
10354
Dianne Hackbornde42bb62009-08-05 12:26:15 -070010355 // At this point there may be remaining entries in mLaunchingProviders
10356 // where we were the only one waiting, so they are no longer of use.
10357 // Look for these and clean up if found.
10358 // XXX Commented out for now. Trying to figure out a way to reproduce
10359 // the actual situation to identify what is actually going on.
10360 if (false) {
10361 for (int i=0; i<NL; i++) {
10362 ContentProviderRecord cpr = (ContentProviderRecord)
10363 mLaunchingProviders.get(i);
10364 if (cpr.clients.size() <= 0 && cpr.externals <= 0) {
10365 synchronized (cpr) {
10366 cpr.launchingApp = null;
10367 cpr.notifyAll();
10368 }
10369 }
10370 }
10371 }
10372
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010373 skipCurrentReceiverLocked(app);
10374
10375 // Unregister any receivers.
10376 if (app.receivers.size() > 0) {
10377 Iterator<ReceiverList> it = app.receivers.iterator();
10378 while (it.hasNext()) {
10379 removeReceiverLocked(it.next());
10380 }
10381 app.receivers.clear();
10382 }
10383
Christopher Tate181fafa2009-05-14 11:12:14 -070010384 // If the app is undergoing backup, tell the backup manager about it
10385 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010386 if (DEBUG_BACKUP) Slog.d(TAG, "App " + mBackupTarget.appInfo + " died during backup");
Christopher Tate181fafa2009-05-14 11:12:14 -070010387 try {
10388 IBackupManager bm = IBackupManager.Stub.asInterface(
10389 ServiceManager.getService(Context.BACKUP_SERVICE));
10390 bm.agentDisconnected(app.info.packageName);
10391 } catch (RemoteException e) {
10392 // can't happen; backup manager is local
10393 }
10394 }
10395
Jeff Sharkey287bd832011-05-28 19:36:26 -070010396 mHandler.obtainMessage(DISPATCH_PROCESS_DIED, app.pid, app.info.uid, null).sendToTarget();
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070010397
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010398 // If the caller is restarting this app, then leave it in its
10399 // current lists and let the caller take care of it.
10400 if (restarting) {
10401 return;
10402 }
10403
10404 if (!app.persistent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010405 if (DEBUG_PROCESSES) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010406 "Removing non-persistent process during cleanup: " + app);
10407 mProcessNames.remove(app.processName, app.info.uid);
Dianne Hackborn860755f2010-06-03 18:47:52 -070010408 if (mHeavyWeightProcess == app) {
10409 mHeavyWeightProcess = null;
10410 mHandler.sendEmptyMessage(CANCEL_HEAVY_NOTIFICATION_MSG);
10411 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010412 } else if (!app.removed) {
10413 // This app is persistent, so we need to keep its record around.
10414 // If it is not already on the pending app list, add it there
10415 // and start a new process for it.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010416 if (mPersistentStartingProcesses.indexOf(app) < 0) {
10417 mPersistentStartingProcesses.add(app);
10418 restart = true;
10419 }
10420 }
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070010421 if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
10422 "Clean-up removing on hold: " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010423 mProcessesOnHold.remove(app);
10424
The Android Open Source Project4df24232009-03-05 14:34:35 -080010425 if (app == mHomeProcess) {
10426 mHomeProcess = null;
10427 }
Dianne Hackbornf35fe232011-11-01 19:25:20 -070010428 if (app == mPreviousProcess) {
10429 mPreviousProcess = null;
10430 }
10431
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010432 if (restart) {
10433 // We have components that still need to be running in the
10434 // process, so re-launch it.
10435 mProcessNames.put(app.processName, app.info.uid, app);
10436 startProcessLocked(app, "restart", app.processName);
10437 } else if (app.pid > 0 && app.pid != MY_PID) {
10438 // Goodbye!
10439 synchronized (mPidsSelfLocked) {
10440 mPidsSelfLocked.remove(app.pid);
10441 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
10442 }
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070010443 app.setPid(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010444 }
10445 }
10446
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010447 boolean checkAppInLaunchingProvidersLocked(ProcessRecord app, boolean alwaysBad) {
10448 // Look through the content providers we are waiting to have launched,
10449 // and if any run in this process then either schedule a restart of
10450 // the process or kill the client waiting for it if this process has
10451 // gone bad.
10452 int NL = mLaunchingProviders.size();
10453 boolean restart = false;
10454 for (int i=0; i<NL; i++) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070010455 ContentProviderRecord cpr = mLaunchingProviders.get(i);
Dianne Hackbornf670ef72009-11-16 13:59:16 -080010456 if (cpr.launchingApp == app) {
10457 if (!alwaysBad && !app.bad) {
10458 restart = true;
10459 } else {
10460 removeDyingProviderLocked(app, cpr);
10461 NL = mLaunchingProviders.size();
10462 }
10463 }
10464 }
10465 return restart;
10466 }
10467
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010468 // =========================================================
10469 // SERVICES
10470 // =========================================================
10471
10472 ActivityManager.RunningServiceInfo makeRunningServiceInfoLocked(ServiceRecord r) {
10473 ActivityManager.RunningServiceInfo info =
10474 new ActivityManager.RunningServiceInfo();
10475 info.service = r.name;
10476 if (r.app != null) {
10477 info.pid = r.app.pid;
10478 }
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010479 info.uid = r.appInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010480 info.process = r.processName;
10481 info.foreground = r.isForeground;
10482 info.activeSince = r.createTime;
10483 info.started = r.startRequested;
10484 info.clientCount = r.connections.size();
10485 info.crashCount = r.crashCount;
10486 info.lastActivityTime = r.lastActivity;
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010487 if (r.isForeground) {
10488 info.flags |= ActivityManager.RunningServiceInfo.FLAG_FOREGROUND;
10489 }
10490 if (r.startRequested) {
10491 info.flags |= ActivityManager.RunningServiceInfo.FLAG_STARTED;
10492 }
Dan Egnor42471dd2010-01-07 17:25:22 -080010493 if (r.app != null && r.app.pid == MY_PID) {
Dianne Hackborn3025ef32009-08-31 21:31:47 -070010494 info.flags |= ActivityManager.RunningServiceInfo.FLAG_SYSTEM_PROCESS;
10495 }
10496 if (r.app != null && r.app.persistent) {
10497 info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
10498 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010499
10500 for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
10501 for (int i=0; i<connl.size(); i++) {
10502 ConnectionRecord conn = connl.get(i);
10503 if (conn.clientLabel != 0) {
10504 info.clientPackage = conn.binding.client.info.packageName;
10505 info.clientLabel = conn.clientLabel;
10506 return info;
10507 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010508 }
10509 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010510 return info;
10511 }
10512
10513 public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
10514 int flags) {
10515 synchronized (this) {
10516 ArrayList<ActivityManager.RunningServiceInfo> res
10517 = new ArrayList<ActivityManager.RunningServiceInfo>();
10518
10519 if (mServices.size() > 0) {
10520 Iterator<ServiceRecord> it = mServices.values().iterator();
10521 while (it.hasNext() && res.size() < maxNum) {
10522 res.add(makeRunningServiceInfoLocked(it.next()));
10523 }
10524 }
10525
10526 for (int i=0; i<mRestartingServices.size() && res.size() < maxNum; i++) {
10527 ServiceRecord r = mRestartingServices.get(i);
10528 ActivityManager.RunningServiceInfo info =
10529 makeRunningServiceInfoLocked(r);
10530 info.restarting = r.nextRestartTime;
10531 res.add(info);
10532 }
10533
10534 return res;
10535 }
10536 }
10537
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010538 public PendingIntent getRunningServiceControlPanel(ComponentName name) {
10539 synchronized (this) {
10540 ServiceRecord r = mServices.get(name);
10541 if (r != null) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010542 for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
10543 for (int i=0; i<conn.size(); i++) {
10544 if (conn.get(i).clientIntent != null) {
10545 return conn.get(i).clientIntent;
10546 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070010547 }
10548 }
10549 }
10550 }
10551 return null;
10552 }
10553
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010554 private final ServiceRecord findServiceLocked(ComponentName name,
10555 IBinder token) {
10556 ServiceRecord r = mServices.get(name);
10557 return r == token ? r : null;
10558 }
10559
10560 private final class ServiceLookupResult {
10561 final ServiceRecord record;
10562 final String permission;
10563
10564 ServiceLookupResult(ServiceRecord _record, String _permission) {
10565 record = _record;
10566 permission = _permission;
10567 }
10568 };
10569
10570 private ServiceLookupResult findServiceLocked(Intent service,
10571 String resolvedType) {
10572 ServiceRecord r = null;
10573 if (service.getComponent() != null) {
10574 r = mServices.get(service.getComponent());
10575 }
10576 if (r == null) {
10577 Intent.FilterComparison filter = new Intent.FilterComparison(service);
10578 r = mServicesByIntent.get(filter);
10579 }
10580
10581 if (r == null) {
10582 try {
10583 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010584 AppGlobals.getPackageManager().resolveService(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010585 service, resolvedType, 0);
10586 ServiceInfo sInfo =
10587 rInfo != null ? rInfo.serviceInfo : null;
10588 if (sInfo == null) {
10589 return null;
10590 }
10591
10592 ComponentName name = new ComponentName(
10593 sInfo.applicationInfo.packageName, sInfo.name);
10594 r = mServices.get(name);
10595 } catch (RemoteException ex) {
10596 // pm is in same process, this will never happen.
10597 }
10598 }
10599 if (r != null) {
10600 int callingPid = Binder.getCallingPid();
10601 int callingUid = Binder.getCallingUid();
10602 if (checkComponentPermission(r.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080010603 callingPid, callingUid, r.appInfo.uid, r.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010604 != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080010605 if (!r.exported) {
10606 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
10607 + " from pid=" + callingPid
10608 + ", uid=" + callingUid
10609 + " that is not exported from uid " + r.appInfo.uid);
10610 return new ServiceLookupResult(null, "not exported from uid "
10611 + r.appInfo.uid);
10612 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080010613 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010614 + " from pid=" + callingPid
10615 + ", uid=" + callingUid
10616 + " requires " + r.permission);
10617 return new ServiceLookupResult(null, r.permission);
10618 }
10619 return new ServiceLookupResult(r, null);
10620 }
10621 return null;
10622 }
10623
10624 private class ServiceRestarter implements Runnable {
10625 private ServiceRecord mService;
10626
10627 void setService(ServiceRecord service) {
10628 mService = service;
10629 }
10630
10631 public void run() {
10632 synchronized(ActivityManagerService.this) {
10633 performServiceRestartLocked(mService);
10634 }
10635 }
10636 }
10637
10638 private ServiceLookupResult retrieveServiceLocked(Intent service,
10639 String resolvedType, int callingPid, int callingUid) {
10640 ServiceRecord r = null;
10641 if (service.getComponent() != null) {
10642 r = mServices.get(service.getComponent());
10643 }
10644 Intent.FilterComparison filter = new Intent.FilterComparison(service);
10645 r = mServicesByIntent.get(filter);
10646 if (r == null) {
10647 try {
10648 ResolveInfo rInfo =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070010649 AppGlobals.getPackageManager().resolveService(
Dianne Hackborn1655be42009-05-08 14:29:01 -070010650 service, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010651 ServiceInfo sInfo =
10652 rInfo != null ? rInfo.serviceInfo : null;
10653 if (sInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010654 Slog.w(TAG, "Unable to start service " + service +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010655 ": not found");
10656 return null;
10657 }
10658
10659 ComponentName name = new ComponentName(
10660 sInfo.applicationInfo.packageName, sInfo.name);
10661 r = mServices.get(name);
10662 if (r == null) {
10663 filter = new Intent.FilterComparison(service.cloneFilter());
10664 ServiceRestarter res = new ServiceRestarter();
10665 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
10666 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
10667 synchronized (stats) {
10668 ss = stats.getServiceStatsLocked(
10669 sInfo.applicationInfo.uid, sInfo.packageName,
10670 sInfo.name);
10671 }
Dianne Hackbornb1c4a2a2010-01-19 15:36:42 -080010672 r = new ServiceRecord(this, ss, name, filter, sInfo, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010673 res.setService(r);
10674 mServices.put(name, r);
10675 mServicesByIntent.put(filter, r);
10676
10677 // Make sure this component isn't in the pending list.
10678 int N = mPendingServices.size();
10679 for (int i=0; i<N; i++) {
10680 ServiceRecord pr = mPendingServices.get(i);
10681 if (pr.name.equals(name)) {
10682 mPendingServices.remove(i);
10683 i--;
10684 N--;
10685 }
10686 }
10687 }
10688 } catch (RemoteException ex) {
10689 // pm is in same process, this will never happen.
10690 }
10691 }
10692 if (r != null) {
10693 if (checkComponentPermission(r.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080010694 callingPid, callingUid, r.appInfo.uid, r.exported)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010695 != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080010696 if (!r.exported) {
10697 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
10698 + " from pid=" + callingPid
10699 + ", uid=" + callingUid
10700 + " that is not exported from uid " + r.appInfo.uid);
10701 return new ServiceLookupResult(null, "not exported from uid "
10702 + r.appInfo.uid);
10703 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080010704 Slog.w(TAG, "Permission Denial: Accessing service " + r.name
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080010705 + " from pid=" + callingPid
10706 + ", uid=" + callingUid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010707 + " requires " + r.permission);
10708 return new ServiceLookupResult(null, r.permission);
10709 }
10710 return new ServiceLookupResult(r, null);
10711 }
10712 return null;
10713 }
10714
Dianne Hackborn287952c2010-09-22 22:34:31 -070010715 private final void bumpServiceExecutingLocked(ServiceRecord r, String why) {
10716 if (DEBUG_SERVICE) Log.v(TAG, ">>> EXECUTING "
10717 + why + " of " + r + " in app " + r.app);
10718 else if (DEBUG_SERVICE_EXECUTING) Log.v(TAG, ">>> EXECUTING "
10719 + why + " of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010720 long now = SystemClock.uptimeMillis();
10721 if (r.executeNesting == 0 && r.app != null) {
10722 if (r.app.executingServices.size() == 0) {
10723 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
10724 msg.obj = r.app;
10725 mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
10726 }
10727 r.app.executingServices.add(r);
10728 }
10729 r.executeNesting++;
10730 r.executingStart = now;
10731 }
10732
10733 private final void sendServiceArgsLocked(ServiceRecord r,
10734 boolean oomAdjusted) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010735 final int N = r.pendingStarts.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010736 if (N == 0) {
10737 return;
10738 }
10739
Dianne Hackborn39792d22010-08-19 18:01:52 -070010740 while (r.pendingStarts.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010741 try {
Dianne Hackborn39792d22010-08-19 18:01:52 -070010742 ServiceRecord.StartItem si = r.pendingStarts.remove(0);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010743 if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
10744 + r + " " + r.intent + " args=" + si.intent);
Dianne Hackborn3a28f222011-03-01 12:25:54 -080010745 if (si.intent == null && N > 1) {
10746 // If somehow we got a dummy null intent in the middle,
10747 // then skip it. DO NOT skip a null intent when it is
10748 // the only one in the list -- this is to support the
10749 // onStartCommand(null) case.
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010750 continue;
10751 }
Dianne Hackborn39792d22010-08-19 18:01:52 -070010752 si.deliveredTime = SystemClock.uptimeMillis();
10753 r.deliveredStarts.add(si);
10754 si.deliveryCount++;
Dianne Hackborn3a28f222011-03-01 12:25:54 -080010755 if (si.targetPermissionUid >= 0 && si.intent != null) {
Dianne Hackborn39792d22010-08-19 18:01:52 -070010756 grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
Dianne Hackborn7e269642010-08-25 19:50:20 -070010757 r.packageName, si.intent, si.getUriPermissionsLocked());
Dianne Hackborn39792d22010-08-19 18:01:52 -070010758 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070010759 bumpServiceExecutingLocked(r, "start");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010760 if (!oomAdjusted) {
10761 oomAdjusted = true;
10762 updateOomAdjLocked(r.app);
10763 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010764 int flags = 0;
10765 if (si.deliveryCount > 0) {
10766 flags |= Service.START_FLAG_RETRY;
10767 }
10768 if (si.doneExecutingCount > 0) {
10769 flags |= Service.START_FLAG_REDELIVERY;
10770 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010771 r.app.thread.scheduleServiceArgs(r, si.taskRemoved, si.id, flags, si.intent);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010772 } catch (RemoteException e) {
10773 // Remote process gone... we'll let the normal cleanup take
10774 // care of this.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010775 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010776 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010777 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010778 Slog.w(TAG, "Unexpected exception", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010779 break;
10780 }
10781 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010782 }
10783
10784 private final boolean requestServiceBindingLocked(ServiceRecord r,
10785 IntentBindRecord i, boolean rebind) {
10786 if (r.app == null || r.app.thread == null) {
10787 // If service is not currently running, can't yet bind.
10788 return false;
10789 }
10790 if ((!i.requested || rebind) && i.apps.size() > 0) {
10791 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -070010792 bumpServiceExecutingLocked(r, "bind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010793 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
10794 if (!rebind) {
10795 i.requested = true;
10796 }
10797 i.hasBound = true;
10798 i.doRebind = false;
10799 } catch (RemoteException e) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070010800 if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010801 return false;
10802 }
10803 }
10804 return true;
10805 }
10806
10807 private final void requestServiceBindingsLocked(ServiceRecord r) {
10808 Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
10809 while (bindings.hasNext()) {
10810 IntentBindRecord i = bindings.next();
10811 if (!requestServiceBindingLocked(r, i, false)) {
10812 break;
10813 }
10814 }
10815 }
10816
10817 private final void realStartServiceLocked(ServiceRecord r,
10818 ProcessRecord app) throws RemoteException {
10819 if (app.thread == null) {
10820 throw new RemoteException();
10821 }
10822
10823 r.app = app;
The Android Open Source Project10592532009-03-18 17:39:46 -070010824 r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010825
10826 app.services.add(r);
Dianne Hackborn287952c2010-09-22 22:34:31 -070010827 bumpServiceExecutingLocked(r, "create");
Dianne Hackborndd71fc82009-12-16 19:24:32 -080010828 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010829
10830 boolean created = false;
10831 try {
Dianne Hackborna33e3f72009-09-29 17:28:24 -070010832 mStringBuilder.setLength(0);
Dianne Hackborn90c52de2011-09-23 12:57:44 -070010833 r.intent.getIntent().toShortString(mStringBuilder, true, false, true);
Doug Zongker2bec3d42009-12-04 12:52:44 -080010834 EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010835 System.identityHashCode(r), r.shortName,
Dianne Hackborna33e3f72009-09-29 17:28:24 -070010836 mStringBuilder.toString(), r.app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010837 synchronized (r.stats.getBatteryStats()) {
10838 r.stats.startLaunchedLocked();
10839 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070010840 ensurePackageDexOpt(r.serviceInfo.packageName);
Dianne Hackborne2515ee2011-04-27 18:52:56 -040010841 app.thread.scheduleCreateService(r, r.serviceInfo,
10842 compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo));
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010843 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010844 created = true;
10845 } finally {
10846 if (!created) {
10847 app.services.remove(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010848 scheduleServiceRestartLocked(r, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010849 }
10850 }
10851
10852 requestServiceBindingsLocked(r);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010853
10854 // If the service is in the started state, and there are no
10855 // pending arguments, then fake up one so its onStartCommand() will
10856 // be called.
10857 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070010858 r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
10859 null, -1));
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010860 }
10861
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010862 sendServiceArgsLocked(r, true);
10863 }
10864
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010865 private final boolean scheduleServiceRestartLocked(ServiceRecord r,
10866 boolean allowCancel) {
10867 boolean canceled = false;
10868
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010869 final long now = SystemClock.uptimeMillis();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010870 long minDuration = SERVICE_RESTART_DURATION;
Dianne Hackborn6ccd2af2009-08-27 12:26:44 -070010871 long resetTime = SERVICE_RESET_RUN_DURATION;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010872
Dianne Hackborn070783f2010-12-29 16:46:28 -080010873 if ((r.serviceInfo.applicationInfo.flags
10874 &ApplicationInfo.FLAG_PERSISTENT) != 0) {
10875 minDuration /= 4;
10876 }
10877
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010878 // Any delivered but not yet finished starts should be put back
10879 // on the pending list.
10880 final int N = r.deliveredStarts.size();
10881 if (N > 0) {
10882 for (int i=N-1; i>=0; i--) {
10883 ServiceRecord.StartItem si = r.deliveredStarts.get(i);
Dianne Hackborn39792d22010-08-19 18:01:52 -070010884 si.removeUriPermissionsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010885 if (si.intent == null) {
10886 // We'll generate this again if needed.
10887 } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT
10888 && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) {
10889 r.pendingStarts.add(0, si);
10890 long dur = SystemClock.uptimeMillis() - si.deliveredTime;
10891 dur *= 2;
10892 if (minDuration < dur) minDuration = dur;
10893 if (resetTime < dur) resetTime = dur;
10894 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010895 Slog.w(TAG, "Canceling start item " + si.intent + " in service "
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010896 + r.name);
10897 canceled = true;
10898 }
10899 }
10900 r.deliveredStarts.clear();
10901 }
10902
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010903 r.totalRestartCount++;
10904 if (r.restartDelay == 0) {
10905 r.restartCount++;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010906 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010907 } else {
10908 // If it has been a "reasonably long time" since the service
10909 // was started, then reset our restart duration back to
10910 // the beginning, so we don't infinitely increase the duration
10911 // on a service that just occasionally gets killed (which is
10912 // a normal case, due to process being killed to reclaim memory).
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010913 if (now > (r.restartTime+resetTime)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010914 r.restartCount = 1;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010915 r.restartDelay = minDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010916 } else {
Dianne Hackborn070783f2010-12-29 16:46:28 -080010917 if ((r.serviceInfo.applicationInfo.flags
10918 &ApplicationInfo.FLAG_PERSISTENT) != 0) {
10919 // Services in peristent processes will restart much more
10920 // quickly, since they are pretty important. (Think SystemUI).
10921 r.restartDelay += minDuration/2;
10922 } else {
10923 r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
10924 if (r.restartDelay < minDuration) {
10925 r.restartDelay = minDuration;
10926 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010927 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010928 }
10929 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010930
10931 r.nextRestartTime = now + r.restartDelay;
10932
10933 // Make sure that we don't end up restarting a bunch of services
10934 // all at the same time.
10935 boolean repeat;
10936 do {
10937 repeat = false;
10938 for (int i=mRestartingServices.size()-1; i>=0; i--) {
10939 ServiceRecord r2 = mRestartingServices.get(i);
10940 if (r2 != r && r.nextRestartTime
10941 >= (r2.nextRestartTime-SERVICE_MIN_RESTART_TIME_BETWEEN)
10942 && r.nextRestartTime
10943 < (r2.nextRestartTime+SERVICE_MIN_RESTART_TIME_BETWEEN)) {
10944 r.nextRestartTime = r2.nextRestartTime + SERVICE_MIN_RESTART_TIME_BETWEEN;
10945 r.restartDelay = r.nextRestartTime - now;
10946 repeat = true;
10947 break;
10948 }
10949 }
10950 } while (repeat);
10951
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010952 if (!mRestartingServices.contains(r)) {
10953 mRestartingServices.add(r);
10954 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010955
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070010956 r.cancelNotification();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010957
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010958 mHandler.removeCallbacks(r.restarter);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070010959 mHandler.postAtTime(r.restarter, r.nextRestartTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010960 r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010961 Slog.w(TAG, "Scheduling restart of crashed service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010962 + r.shortName + " in " + r.restartDelay + "ms");
Doug Zongker2bec3d42009-12-04 12:52:44 -080010963 EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010964 r.shortName, r.restartDelay);
10965
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070010966 return canceled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010967 }
10968
10969 final void performServiceRestartLocked(ServiceRecord r) {
10970 if (!mRestartingServices.contains(r)) {
10971 return;
10972 }
10973 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), true);
10974 }
10975
10976 private final boolean unscheduleServiceRestartLocked(ServiceRecord r) {
10977 if (r.restartDelay == 0) {
10978 return false;
10979 }
10980 r.resetRestartCounter();
10981 mRestartingServices.remove(r);
10982 mHandler.removeCallbacks(r.restarter);
10983 return true;
10984 }
10985
10986 private final boolean bringUpServiceLocked(ServiceRecord r,
10987 int intentFlags, boolean whileRestarting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010988 //Slog.i(TAG, "Bring up service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010989 //r.dump(" ");
10990
Dianne Hackborn36124872009-10-08 16:22:03 -070010991 if (r.app != null && r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010992 sendServiceArgsLocked(r, false);
10993 return true;
10994 }
10995
10996 if (!whileRestarting && r.restartDelay > 0) {
10997 // If waiting for a restart, then do nothing.
10998 return true;
10999 }
11000
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011001 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011002
Dianne Hackbornde42bb62009-08-05 12:26:15 -070011003 // We are now bringing the service up, so no longer in the
11004 // restarting state.
11005 mRestartingServices.remove(r);
11006
Dianne Hackborne7f97212011-02-24 14:40:20 -080011007 // Service is now being launched, its package can't be stopped.
11008 try {
11009 AppGlobals.getPackageManager().setPackageStoppedState(
11010 r.packageName, false);
11011 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -080011012 } catch (IllegalArgumentException e) {
11013 Slog.w(TAG, "Failed trying to unstop package "
11014 + r.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -080011015 }
11016
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011017 final String appName = r.processName;
11018 ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
11019 if (app != null && app.thread != null) {
11020 try {
Dianne Hackborn6c418d52011-06-29 14:05:33 -070011021 app.addPackage(r.appInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011022 realStartServiceLocked(r, app);
11023 return true;
11024 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011025 Slog.w(TAG, "Exception when starting service " + r.shortName, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011026 }
11027
11028 // If a dead object exception was thrown -- fall through to
11029 // restart the application.
11030 }
11031
Dianne Hackborn36124872009-10-08 16:22:03 -070011032 // Not running -- get it started, and enqueue this service record
11033 // to be executed when the app comes up.
11034 if (startProcessLocked(appName, r.appInfo, true, intentFlags,
11035 "service", r.name, false) == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011036 Slog.w(TAG, "Unable to launch app "
Dianne Hackborn36124872009-10-08 16:22:03 -070011037 + r.appInfo.packageName + "/"
11038 + r.appInfo.uid + " for service "
11039 + r.intent.getIntent() + ": process is bad");
11040 bringDownServiceLocked(r, true);
11041 return false;
11042 }
11043
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011044 if (!mPendingServices.contains(r)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011045 mPendingServices.add(r);
11046 }
Dianne Hackborn36124872009-10-08 16:22:03 -070011047
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011048 return true;
11049 }
11050
11051 private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011052 //Slog.i(TAG, "Bring down service:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011053 //r.dump(" ");
11054
11055 // Does it still need to run?
11056 if (!force && r.startRequested) {
11057 return;
11058 }
11059 if (r.connections.size() > 0) {
11060 if (!force) {
11061 // XXX should probably keep a count of the number of auto-create
11062 // connections directly in the service.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011063 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011064 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011065 ArrayList<ConnectionRecord> cr = it.next();
11066 for (int i=0; i<cr.size(); i++) {
11067 if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
11068 return;
11069 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011070 }
11071 }
11072 }
11073
11074 // Report to all of the connections that the service is no longer
11075 // available.
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011076 Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011077 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011078 ArrayList<ConnectionRecord> c = it.next();
11079 for (int i=0; i<c.size(); i++) {
Dianne Hackborn130b0d22011-07-26 22:07:48 -070011080 ConnectionRecord cr = c.get(i);
11081 // There is still a connection to the service that is
11082 // being brought down. Mark it as dead.
11083 cr.serviceDead = true;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011084 try {
Dianne Hackborn130b0d22011-07-26 22:07:48 -070011085 cr.conn.connected(r.name, null);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011086 } catch (Exception e) {
11087 Slog.w(TAG, "Failure disconnecting service " + r.name +
11088 " to connection " + c.get(i).conn.asBinder() +
11089 " (in " + c.get(i).binding.client.processName + ")", e);
11090 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011091 }
11092 }
11093 }
11094
11095 // Tell the service that it has been unbound.
11096 if (r.bindings.size() > 0 && r.app != null && r.app.thread != null) {
11097 Iterator<IntentBindRecord> it = r.bindings.values().iterator();
11098 while (it.hasNext()) {
11099 IntentBindRecord ibr = it.next();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011100 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011101 + ": hasBound=" + ibr.hasBound);
11102 if (r.app != null && r.app.thread != null && ibr.hasBound) {
11103 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -070011104 bumpServiceExecutingLocked(r, "bring down unbind");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011105 updateOomAdjLocked(r.app);
11106 ibr.hasBound = false;
11107 r.app.thread.scheduleUnbindService(r,
11108 ibr.intent.getIntent());
11109 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011110 Slog.w(TAG, "Exception when unbinding service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011111 + r.shortName, e);
11112 serviceDoneExecutingLocked(r, true);
11113 }
11114 }
11115 }
11116 }
11117
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011118 if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
Doug Zongker2bec3d42009-12-04 12:52:44 -080011119 EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011120 System.identityHashCode(r), r.shortName,
11121 (r.app != null) ? r.app.pid : -1);
11122
11123 mServices.remove(r.name);
11124 mServicesByIntent.remove(r.intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011125 r.totalRestartCount = 0;
11126 unscheduleServiceRestartLocked(r);
11127
11128 // Also make sure it is not on the pending list.
11129 int N = mPendingServices.size();
11130 for (int i=0; i<N; i++) {
11131 if (mPendingServices.get(i) == r) {
11132 mPendingServices.remove(i);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011133 if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011134 i--;
11135 N--;
11136 }
11137 }
11138
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011139 r.cancelNotification();
11140 r.isForeground = false;
11141 r.foregroundId = 0;
11142 r.foregroundNoti = null;
11143
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011144 // Clear start entries.
Dianne Hackborn39792d22010-08-19 18:01:52 -070011145 r.clearDeliveredStartsLocked();
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011146 r.pendingStarts.clear();
11147
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011148 if (r.app != null) {
11149 synchronized (r.stats.getBatteryStats()) {
11150 r.stats.stopLaunchedLocked();
11151 }
11152 r.app.services.remove(r);
11153 if (r.app.thread != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011154 try {
Dianne Hackborn287952c2010-09-22 22:34:31 -070011155 bumpServiceExecutingLocked(r, "stop");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011156 mStoppingServices.add(r);
11157 updateOomAdjLocked(r.app);
11158 r.app.thread.scheduleStopService(r);
11159 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011160 Slog.w(TAG, "Exception when stopping service "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011161 + r.shortName, e);
11162 serviceDoneExecutingLocked(r, true);
11163 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011164 updateServiceForegroundLocked(r.app, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011165 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011166 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011167 TAG, "Removed service that has no process: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011168 }
11169 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011170 if (DEBUG_SERVICE) Slog.v(
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011171 TAG, "Removed service that is not running: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011172 }
Vairavan Srinivasana207ce22010-12-23 13:51:48 -080011173
11174 if (r.bindings.size() > 0) {
11175 r.bindings.clear();
11176 }
11177
11178 if (r.restarter instanceof ServiceRestarter) {
11179 ((ServiceRestarter)r.restarter).setService(null);
11180 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011181 }
11182
11183 ComponentName startServiceLocked(IApplicationThread caller,
11184 Intent service, String resolvedType,
11185 int callingPid, int callingUid) {
11186 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011187 if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011188 + " type=" + resolvedType + " args=" + service.getExtras());
11189
11190 if (caller != null) {
11191 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11192 if (callerApp == null) {
11193 throw new SecurityException(
11194 "Unable to find app for caller " + caller
11195 + " (pid=" + Binder.getCallingPid()
11196 + ") when starting service " + service);
11197 }
11198 }
11199
11200 ServiceLookupResult res =
11201 retrieveServiceLocked(service, resolvedType,
11202 callingPid, callingUid);
11203 if (res == null) {
11204 return null;
11205 }
11206 if (res.record == null) {
11207 return new ComponentName("!", res.permission != null
11208 ? res.permission : "private to package");
11209 }
11210 ServiceRecord r = res.record;
Dianne Hackborn39792d22010-08-19 18:01:52 -070011211 int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
11212 callingUid, r.packageName, service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011213 if (unscheduleServiceRestartLocked(r)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011214 if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011215 }
11216 r.startRequested = true;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011217 r.callStart = false;
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070011218 r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
Dianne Hackborn39792d22010-08-19 18:01:52 -070011219 service, targetPermissionUid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011220 r.lastActivity = SystemClock.uptimeMillis();
11221 synchronized (r.stats.getBatteryStats()) {
11222 r.stats.startRunningLocked();
11223 }
11224 if (!bringUpServiceLocked(r, service.getFlags(), false)) {
11225 return new ComponentName("!", "Service process is bad");
11226 }
11227 return r.name;
11228 }
11229 }
11230
11231 public ComponentName startService(IApplicationThread caller, Intent service,
11232 String resolvedType) {
11233 // Refuse possible leaked file descriptors
11234 if (service != null && service.hasFileDescriptors() == true) {
11235 throw new IllegalArgumentException("File descriptors passed in Intent");
11236 }
11237
11238 synchronized(this) {
11239 final int callingPid = Binder.getCallingPid();
11240 final int callingUid = Binder.getCallingUid();
11241 final long origId = Binder.clearCallingIdentity();
11242 ComponentName res = startServiceLocked(caller, service,
11243 resolvedType, callingPid, callingUid);
11244 Binder.restoreCallingIdentity(origId);
11245 return res;
11246 }
11247 }
11248
11249 ComponentName startServiceInPackage(int uid,
11250 Intent service, String resolvedType) {
11251 synchronized(this) {
11252 final long origId = Binder.clearCallingIdentity();
11253 ComponentName res = startServiceLocked(null, service,
11254 resolvedType, -1, uid);
11255 Binder.restoreCallingIdentity(origId);
11256 return res;
11257 }
11258 }
11259
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070011260 private void stopServiceLocked(ServiceRecord service) {
11261 synchronized (service.stats.getBatteryStats()) {
11262 service.stats.stopRunningLocked();
11263 }
11264 service.startRequested = false;
11265 service.callStart = false;
11266 bringDownServiceLocked(service, false);
11267 }
11268
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011269 public int stopService(IApplicationThread caller, Intent service,
11270 String resolvedType) {
11271 // Refuse possible leaked file descriptors
11272 if (service != null && service.hasFileDescriptors() == true) {
11273 throw new IllegalArgumentException("File descriptors passed in Intent");
11274 }
11275
11276 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011277 if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011278 + " type=" + resolvedType);
11279
11280 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11281 if (caller != null && callerApp == null) {
11282 throw new SecurityException(
11283 "Unable to find app for caller " + caller
11284 + " (pid=" + Binder.getCallingPid()
11285 + ") when stopping service " + service);
11286 }
11287
11288 // If this service is active, make sure it is stopped.
11289 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11290 if (r != null) {
11291 if (r.record != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011292 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070011293 try {
11294 stopServiceLocked(r.record);
11295 } finally {
11296 Binder.restoreCallingIdentity(origId);
11297 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011298 return 1;
11299 }
11300 return -1;
11301 }
11302 }
11303
11304 return 0;
11305 }
11306
11307 public IBinder peekService(Intent service, String resolvedType) {
11308 // Refuse possible leaked file descriptors
11309 if (service != null && service.hasFileDescriptors() == true) {
11310 throw new IllegalArgumentException("File descriptors passed in Intent");
11311 }
11312
11313 IBinder ret = null;
11314
11315 synchronized(this) {
11316 ServiceLookupResult r = findServiceLocked(service, resolvedType);
11317
11318 if (r != null) {
11319 // r.record is null if findServiceLocked() failed the caller permission check
11320 if (r.record == null) {
11321 throw new SecurityException(
11322 "Permission Denial: Accessing service " + r.record.name
11323 + " from pid=" + Binder.getCallingPid()
11324 + ", uid=" + Binder.getCallingUid()
11325 + " requires " + r.permission);
11326 }
11327 IntentBindRecord ib = r.record.bindings.get(r.record.intent);
11328 if (ib != null) {
11329 ret = ib.binder;
11330 }
11331 }
11332 }
11333
11334 return ret;
11335 }
11336
11337 public boolean stopServiceToken(ComponentName className, IBinder token,
11338 int startId) {
11339 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011340 if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011341 + " " + token + " startId=" + startId);
11342 ServiceRecord r = findServiceLocked(className, token);
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011343 if (r != null) {
11344 if (startId >= 0) {
11345 // Asked to only stop if done with all work. Note that
11346 // to avoid leaks, we will take this as dropping all
11347 // start items up to and including this one.
11348 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
11349 if (si != null) {
11350 while (r.deliveredStarts.size() > 0) {
Dianne Hackborn39792d22010-08-19 18:01:52 -070011351 ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
11352 cur.removeUriPermissionsLocked();
11353 if (cur == si) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011354 break;
11355 }
11356 }
11357 }
11358
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070011359 if (r.getLastStartId() != startId) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011360 return false;
11361 }
11362
11363 if (r.deliveredStarts.size() > 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011364 Slog.w(TAG, "stopServiceToken startId " + startId
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011365 + " is last, but have " + r.deliveredStarts.size()
11366 + " remaining args");
11367 }
11368 }
11369
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011370 synchronized (r.stats.getBatteryStats()) {
11371 r.stats.stopRunningLocked();
11372 r.startRequested = false;
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011373 r.callStart = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011374 }
11375 final long origId = Binder.clearCallingIdentity();
11376 bringDownServiceLocked(r, false);
11377 Binder.restoreCallingIdentity(origId);
11378 return true;
11379 }
11380 }
11381 return false;
11382 }
11383
11384 public void setServiceForeground(ComponentName className, IBinder token,
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011385 int id, Notification notification, boolean removeNotification) {
11386 final long origId = Binder.clearCallingIdentity();
11387 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011388 synchronized(this) {
11389 ServiceRecord r = findServiceLocked(className, token);
11390 if (r != null) {
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011391 if (id != 0) {
11392 if (notification == null) {
11393 throw new IllegalArgumentException("null notification");
11394 }
11395 if (r.foregroundId != id) {
11396 r.cancelNotification();
11397 r.foregroundId = id;
11398 }
11399 notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
11400 r.foregroundNoti = notification;
11401 r.isForeground = true;
11402 r.postNotification();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011403 if (r.app != null) {
11404 updateServiceForegroundLocked(r.app, true);
11405 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011406 } else {
11407 if (r.isForeground) {
11408 r.isForeground = false;
11409 if (r.app != null) {
Dianne Hackborn8633e682010-04-22 16:03:41 -070011410 updateLruProcessLocked(r.app, false, true);
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011411 updateServiceForegroundLocked(r.app, true);
11412 }
11413 }
11414 if (removeNotification) {
11415 r.cancelNotification();
11416 r.foregroundId = 0;
11417 r.foregroundNoti = null;
11418 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011419 }
11420 }
11421 }
Dianne Hackbornd8a43f62009-08-17 23:33:56 -070011422 } finally {
11423 Binder.restoreCallingIdentity(origId);
11424 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011425 }
11426
11427 public void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
11428 boolean anyForeground = false;
Dianne Hackborn860755f2010-06-03 18:47:52 -070011429 for (ServiceRecord sr : proc.services) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011430 if (sr.isForeground) {
11431 anyForeground = true;
11432 break;
11433 }
11434 }
11435 if (anyForeground != proc.foregroundServices) {
11436 proc.foregroundServices = anyForeground;
11437 if (oomAdj) {
11438 updateOomAdjLocked();
11439 }
11440 }
11441 }
11442
11443 public int bindService(IApplicationThread caller, IBinder token,
11444 Intent service, String resolvedType,
11445 IServiceConnection connection, int flags) {
11446 // Refuse possible leaked file descriptors
11447 if (service != null && service.hasFileDescriptors() == true) {
11448 throw new IllegalArgumentException("File descriptors passed in Intent");
11449 }
11450
11451 synchronized(this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011452 if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011453 + " type=" + resolvedType + " conn=" + connection.asBinder()
11454 + " flags=0x" + Integer.toHexString(flags));
11455 final ProcessRecord callerApp = getRecordForAppLocked(caller);
11456 if (callerApp == null) {
11457 throw new SecurityException(
11458 "Unable to find app for caller " + caller
11459 + " (pid=" + Binder.getCallingPid()
11460 + ") when binding service " + service);
11461 }
11462
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011463 ActivityRecord activity = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011464 if (token != null) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -070011465 activity = mMainStack.isInStackLocked(token);
11466 if (activity == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011467 Slog.w(TAG, "Binding with unknown activity: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011468 return 0;
11469 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011470 }
11471
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011472 int clientLabel = 0;
11473 PendingIntent clientIntent = null;
11474
11475 if (callerApp.info.uid == Process.SYSTEM_UID) {
11476 // Hacky kind of thing -- allow system stuff to tell us
11477 // what they are, so we can report this elsewhere for
11478 // others to know why certain services are running.
11479 try {
11480 clientIntent = (PendingIntent)service.getParcelableExtra(
11481 Intent.EXTRA_CLIENT_INTENT);
11482 } catch (RuntimeException e) {
11483 }
11484 if (clientIntent != null) {
11485 clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
11486 if (clientLabel != 0) {
11487 // There are no useful extras in the intent, trash them.
11488 // System code calling with this stuff just needs to know
11489 // this will happen.
11490 service = service.cloneFilter();
11491 }
11492 }
11493 }
11494
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011495 ServiceLookupResult res =
11496 retrieveServiceLocked(service, resolvedType,
11497 Binder.getCallingPid(), Binder.getCallingUid());
11498 if (res == null) {
11499 return 0;
11500 }
11501 if (res.record == null) {
11502 return -1;
11503 }
11504 ServiceRecord s = res.record;
11505
11506 final long origId = Binder.clearCallingIdentity();
11507
11508 if (unscheduleServiceRestartLocked(s)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011509 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011510 + s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011511 }
11512
11513 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
11514 ConnectionRecord c = new ConnectionRecord(b, activity,
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070011515 connection, flags, clientLabel, clientIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011516
11517 IBinder binder = connection.asBinder();
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011518 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
11519 if (clist == null) {
11520 clist = new ArrayList<ConnectionRecord>();
11521 s.connections.put(binder, clist);
11522 }
11523 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011524 b.connections.add(c);
11525 if (activity != null) {
11526 if (activity.connections == null) {
11527 activity.connections = new HashSet<ConnectionRecord>();
11528 }
11529 activity.connections.add(c);
11530 }
11531 b.client.connections.add(c);
Dianne Hackbornc68c9132011-07-29 01:25:18 -070011532 if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) {
11533 b.client.hasAboveClient = true;
11534 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011535 clist = mServiceConnections.get(binder);
11536 if (clist == null) {
11537 clist = new ArrayList<ConnectionRecord>();
11538 mServiceConnections.put(binder, clist);
11539 }
11540 clist.add(c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011541
11542 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
11543 s.lastActivity = SystemClock.uptimeMillis();
11544 if (!bringUpServiceLocked(s, service.getFlags(), false)) {
11545 return 0;
11546 }
11547 }
11548
11549 if (s.app != null) {
11550 // This could have made the service more important.
11551 updateOomAdjLocked(s.app);
11552 }
11553
Joe Onorato8a9b2202010-02-26 18:56:32 -080011554 if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011555 + ": received=" + b.intent.received
11556 + " apps=" + b.intent.apps.size()
11557 + " doRebind=" + b.intent.doRebind);
11558
11559 if (s.app != null && b.intent.received) {
11560 // Service is already running, so we can immediately
11561 // publish the connection.
11562 try {
11563 c.conn.connected(s.name, b.intent.binder);
11564 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011565 Slog.w(TAG, "Failure sending service " + s.shortName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011566 + " to connection " + c.conn.asBinder()
11567 + " (in " + c.binding.client.processName + ")", e);
11568 }
11569
11570 // If this is the first app connected back to this binding,
11571 // and the service had previously asked to be told when
11572 // rebound, then do so.
11573 if (b.intent.apps.size() == 1 && b.intent.doRebind) {
11574 requestServiceBindingLocked(s, b.intent, true);
11575 }
11576 } else if (!b.intent.requested) {
11577 requestServiceBindingLocked(s, b.intent, false);
11578 }
11579
11580 Binder.restoreCallingIdentity(origId);
11581 }
11582
11583 return 1;
11584 }
11585
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070011586 void removeConnectionLocked(
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070011587 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011588 IBinder binder = c.conn.asBinder();
11589 AppBindRecord b = c.binding;
11590 ServiceRecord s = b.service;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011591 ArrayList<ConnectionRecord> clist = s.connections.get(binder);
11592 if (clist != null) {
11593 clist.remove(c);
11594 if (clist.size() == 0) {
11595 s.connections.remove(binder);
11596 }
11597 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011598 b.connections.remove(c);
11599 if (c.activity != null && c.activity != skipAct) {
11600 if (c.activity.connections != null) {
11601 c.activity.connections.remove(c);
11602 }
11603 }
11604 if (b.client != skipApp) {
11605 b.client.connections.remove(c);
Dianne Hackbornc68c9132011-07-29 01:25:18 -070011606 if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) {
11607 b.client.updateHasAboveClientLocked();
11608 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011609 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011610 clist = mServiceConnections.get(binder);
11611 if (clist != null) {
11612 clist.remove(c);
11613 if (clist.size() == 0) {
11614 mServiceConnections.remove(binder);
11615 }
11616 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011617
11618 if (b.connections.size() == 0) {
11619 b.intent.apps.remove(b.client);
11620 }
11621
Dianne Hackborn130b0d22011-07-26 22:07:48 -070011622 if (!c.serviceDead) {
11623 if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
11624 + ": shouldUnbind=" + b.intent.hasBound);
11625 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
11626 && b.intent.hasBound) {
11627 try {
11628 bumpServiceExecutingLocked(s, "unbind");
11629 updateOomAdjLocked(s.app);
11630 b.intent.hasBound = false;
11631 // Assume the client doesn't want to know about a rebind;
11632 // we will deal with that later if it asks for one.
11633 b.intent.doRebind = false;
11634 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
11635 } catch (Exception e) {
11636 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
11637 serviceDoneExecutingLocked(s, true);
11638 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011639 }
Dianne Hackborn130b0d22011-07-26 22:07:48 -070011640
11641 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
11642 bringDownServiceLocked(s, false);
11643 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011644 }
11645 }
11646
11647 public boolean unbindService(IServiceConnection connection) {
11648 synchronized (this) {
11649 IBinder binder = connection.asBinder();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011650 if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011651 ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
11652 if (clist == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011653 Slog.w(TAG, "Unbind failed: could not find connection for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011654 + connection.asBinder());
11655 return false;
11656 }
11657
11658 final long origId = Binder.clearCallingIdentity();
11659
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011660 while (clist.size() > 0) {
11661 ConnectionRecord r = clist.get(0);
11662 removeConnectionLocked(r, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011663
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011664 if (r.binding.service.app != null) {
11665 // This could have made the service less important.
11666 updateOomAdjLocked(r.binding.service.app);
11667 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011668 }
11669
11670 Binder.restoreCallingIdentity(origId);
11671 }
11672
11673 return true;
11674 }
11675
11676 public void publishService(IBinder token, Intent intent, IBinder service) {
11677 // Refuse possible leaked file descriptors
11678 if (intent != null && intent.hasFileDescriptors() == true) {
11679 throw new IllegalArgumentException("File descriptors passed in Intent");
11680 }
11681
11682 synchronized(this) {
11683 if (!(token instanceof ServiceRecord)) {
11684 throw new IllegalArgumentException("Invalid service token");
11685 }
11686 ServiceRecord r = (ServiceRecord)token;
11687
11688 final long origId = Binder.clearCallingIdentity();
11689
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011690 if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011691 + " " + intent + ": " + service);
11692 if (r != null) {
11693 Intent.FilterComparison filter
11694 = new Intent.FilterComparison(intent);
11695 IntentBindRecord b = r.bindings.get(filter);
11696 if (b != null && !b.received) {
11697 b.binder = service;
11698 b.requested = true;
11699 b.received = true;
11700 if (r.connections.size() > 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011701 Iterator<ArrayList<ConnectionRecord>> it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011702 = r.connections.values().iterator();
11703 while (it.hasNext()) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011704 ArrayList<ConnectionRecord> clist = it.next();
11705 for (int i=0; i<clist.size(); i++) {
11706 ConnectionRecord c = clist.get(i);
11707 if (!filter.equals(c.binding.intent.intent)) {
11708 if (DEBUG_SERVICE) Slog.v(
11709 TAG, "Not publishing to: " + c);
11710 if (DEBUG_SERVICE) Slog.v(
11711 TAG, "Bound intent: " + c.binding.intent.intent);
11712 if (DEBUG_SERVICE) Slog.v(
11713 TAG, "Published intent: " + intent);
11714 continue;
11715 }
11716 if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
11717 try {
11718 c.conn.connected(r.name, service);
11719 } catch (Exception e) {
11720 Slog.w(TAG, "Failure sending service " + r.name +
11721 " to connection " + c.conn.asBinder() +
11722 " (in " + c.binding.client.processName + ")", e);
11723 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011724 }
11725 }
11726 }
11727 }
11728
11729 serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
11730
11731 Binder.restoreCallingIdentity(origId);
11732 }
11733 }
11734 }
11735
11736 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
11737 // Refuse possible leaked file descriptors
11738 if (intent != null && intent.hasFileDescriptors() == true) {
11739 throw new IllegalArgumentException("File descriptors passed in Intent");
11740 }
11741
11742 synchronized(this) {
11743 if (!(token instanceof ServiceRecord)) {
11744 throw new IllegalArgumentException("Invalid service token");
11745 }
11746 ServiceRecord r = (ServiceRecord)token;
11747
11748 final long origId = Binder.clearCallingIdentity();
11749
11750 if (r != null) {
11751 Intent.FilterComparison filter
11752 = new Intent.FilterComparison(intent);
11753 IntentBindRecord b = r.bindings.get(filter);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011754 if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011755 + " at " + b + ": apps="
11756 + (b != null ? b.apps.size() : 0));
Per Edelberg78f9fff2010-08-30 20:01:35 +020011757
11758 boolean inStopping = mStoppingServices.contains(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011759 if (b != null) {
Per Edelberg78f9fff2010-08-30 20:01:35 +020011760 if (b.apps.size() > 0 && !inStopping) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011761 // Applications have already bound since the last
11762 // unbind, so just rebind right here.
11763 requestServiceBindingLocked(r, b, true);
11764 } else {
11765 // Note to tell the service the next time there is
11766 // a new client.
11767 b.doRebind = true;
11768 }
11769 }
11770
Per Edelberg78f9fff2010-08-30 20:01:35 +020011771 serviceDoneExecutingLocked(r, inStopping);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011772
11773 Binder.restoreCallingIdentity(origId);
11774 }
11775 }
11776 }
11777
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011778 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011779 synchronized(this) {
11780 if (!(token instanceof ServiceRecord)) {
11781 throw new IllegalArgumentException("Invalid service token");
11782 }
11783 ServiceRecord r = (ServiceRecord)token;
11784 boolean inStopping = mStoppingServices.contains(token);
11785 if (r != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011786 if (r != token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011787 Slog.w(TAG, "Done executing service " + r.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011788 + " with incorrect token: given " + token
11789 + ", expected " + r);
11790 return;
11791 }
11792
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011793 if (type == 1) {
11794 // This is a call from a service start... take care of
11795 // book-keeping.
11796 r.callStart = true;
11797 switch (res) {
11798 case Service.START_STICKY_COMPATIBILITY:
11799 case Service.START_STICKY: {
11800 // We are done with the associated start arguments.
11801 r.findDeliveredStart(startId, true);
11802 // Don't stop if killed.
11803 r.stopIfKilled = false;
11804 break;
11805 }
11806 case Service.START_NOT_STICKY: {
11807 // We are done with the associated start arguments.
11808 r.findDeliveredStart(startId, true);
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070011809 if (r.getLastStartId() == startId) {
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011810 // There is no more work, and this service
11811 // doesn't want to hang around if killed.
11812 r.stopIfKilled = true;
11813 }
11814 break;
11815 }
11816 case Service.START_REDELIVER_INTENT: {
11817 // We'll keep this item until they explicitly
11818 // call stop for it, but keep track of the fact
11819 // that it was delivered.
11820 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
11821 if (si != null) {
11822 si.deliveryCount = 0;
11823 si.doneExecutingCount++;
11824 // Don't stop if killed.
11825 r.stopIfKilled = true;
11826 }
11827 break;
11828 }
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070011829 case Service.START_TASK_REMOVED_COMPLETE: {
11830 // Special processing for onTaskRemoved(). Don't
11831 // impact normal onStartCommand() processing.
11832 r.findDeliveredStart(startId, true);
11833 break;
11834 }
Dianne Hackbornf6f9f2d2009-08-21 16:26:03 -070011835 default:
11836 throw new IllegalArgumentException(
11837 "Unknown service start result: " + res);
11838 }
11839 if (res == Service.START_STICKY_COMPATIBILITY) {
11840 r.callStart = false;
11841 }
11842 }
11843
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011844 final long origId = Binder.clearCallingIdentity();
11845 serviceDoneExecutingLocked(r, inStopping);
11846 Binder.restoreCallingIdentity(origId);
11847 } else {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011848 Slog.w(TAG, "Done executing unknown service from pid "
11849 + Binder.getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011850 }
11851 }
11852 }
11853
11854 public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070011855 if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
11856 + ": nesting=" + r.executeNesting
11857 + ", inStopping=" + inStopping + ", app=" + r.app);
Dianne Hackborn287952c2010-09-22 22:34:31 -070011858 else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011859 r.executeNesting--;
11860 if (r.executeNesting <= 0 && r.app != null) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070011861 if (DEBUG_SERVICE) Slog.v(TAG,
11862 "Nesting at 0 of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011863 r.app.executingServices.remove(r);
11864 if (r.app.executingServices.size() == 0) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070011865 if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,
11866 "No more executingServices of " + r.shortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011867 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
11868 }
11869 if (inStopping) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070011870 if (DEBUG_SERVICE) Slog.v(TAG,
11871 "doneExecuting remove stopping " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011872 mStoppingServices.remove(r);
Mattias Petersson3996b412010-10-27 09:32:51 +020011873 r.bindings.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011874 }
11875 updateOomAdjLocked(r.app);
11876 }
11877 }
11878
11879 void serviceTimeout(ProcessRecord proc) {
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011880 String anrMessage = null;
11881
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011882 synchronized(this) {
11883 if (proc.executingServices.size() == 0 || proc.thread == null) {
11884 return;
11885 }
11886 long maxTime = SystemClock.uptimeMillis() - SERVICE_TIMEOUT;
11887 Iterator<ServiceRecord> it = proc.executingServices.iterator();
11888 ServiceRecord timeout = null;
11889 long nextTime = 0;
11890 while (it.hasNext()) {
11891 ServiceRecord sr = it.next();
11892 if (sr.executingStart < maxTime) {
11893 timeout = sr;
11894 break;
11895 }
11896 if (sr.executingStart > nextTime) {
11897 nextTime = sr.executingStart;
11898 }
11899 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080011900 if (timeout != null && mLruProcesses.contains(proc)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011901 Slog.w(TAG, "Timeout executing service: " + timeout);
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011902 anrMessage = "Executing service " + timeout.shortName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011903 } else {
11904 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
11905 msg.obj = proc;
11906 mHandler.sendMessageAtTime(msg, nextTime+SERVICE_TIMEOUT);
11907 }
11908 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070011909
11910 if (anrMessage != null) {
11911 appNotResponding(proc, null, null, anrMessage);
11912 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011913 }
11914
11915 // =========================================================
Christopher Tate181fafa2009-05-14 11:12:14 -070011916 // BACKUP AND RESTORE
11917 // =========================================================
11918
11919 // Cause the target app to be launched if necessary and its backup agent
11920 // instantiated. The backup agent will invoke backupAgentCreated() on the
11921 // activity manager to announce its creation.
11922 public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011923 if (DEBUG_BACKUP) Slog.v(TAG, "startBackupAgent: app=" + app + " mode=" + backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070011924 enforceCallingPermission("android.permission.BACKUP", "startBackupAgent");
11925
11926 synchronized(this) {
11927 // !!! TODO: currently no check here that we're already bound
11928 BatteryStatsImpl.Uid.Pkg.Serv ss = null;
11929 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
11930 synchronized (stats) {
11931 ss = stats.getServiceStatsLocked(app.uid, app.packageName, app.name);
11932 }
11933
Dianne Hackborne7f97212011-02-24 14:40:20 -080011934 // Backup agent is now in use, its package can't be stopped.
11935 try {
11936 AppGlobals.getPackageManager().setPackageStoppedState(
11937 app.packageName, false);
11938 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -080011939 } catch (IllegalArgumentException e) {
11940 Slog.w(TAG, "Failed trying to unstop package "
11941 + app.packageName + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -080011942 }
11943
Christopher Tate181fafa2009-05-14 11:12:14 -070011944 BackupRecord r = new BackupRecord(ss, app, backupMode);
Christopher Tate4a627c72011-04-01 14:43:32 -070011945 ComponentName hostingName = (backupMode == IApplicationThread.BACKUP_MODE_INCREMENTAL)
11946 ? new ComponentName(app.packageName, app.backupAgentName)
11947 : new ComponentName("android", "FullBackupAgent");
Christopher Tate181fafa2009-05-14 11:12:14 -070011948 // startProcessLocked() returns existing proc's record if it's already running
11949 ProcessRecord proc = startProcessLocked(app.processName, app,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070011950 false, 0, "backup", hostingName, false);
Christopher Tate181fafa2009-05-14 11:12:14 -070011951 if (proc == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011952 Slog.e(TAG, "Unable to start backup agent process " + r);
Christopher Tate181fafa2009-05-14 11:12:14 -070011953 return false;
11954 }
11955
11956 r.app = proc;
11957 mBackupTarget = r;
11958 mBackupAppName = app.packageName;
11959
Christopher Tate6fa95972009-06-05 18:43:55 -070011960 // Try not to kill the process during backup
11961 updateOomAdjLocked(proc);
11962
Christopher Tate181fafa2009-05-14 11:12:14 -070011963 // If the process is already attached, schedule the creation of the backup agent now.
11964 // If it is not yet live, this will be done when it attaches to the framework.
11965 if (proc.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011966 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
Christopher Tate181fafa2009-05-14 11:12:14 -070011967 try {
Dianne Hackborne2515ee2011-04-27 18:52:56 -040011968 proc.thread.scheduleCreateBackupAgent(app,
11969 compatibilityInfoForPackageLocked(app), backupMode);
Christopher Tate181fafa2009-05-14 11:12:14 -070011970 } catch (RemoteException e) {
Christopher Tate436344a2009-09-30 16:17:37 -070011971 // Will time out on the backup manager side
Christopher Tate181fafa2009-05-14 11:12:14 -070011972 }
11973 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011974 if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc not running, waiting for attach");
Christopher Tate181fafa2009-05-14 11:12:14 -070011975 }
11976 // Invariants: at this point, the target app process exists and the application
11977 // is either already running or in the process of coming up. mBackupTarget and
11978 // mBackupAppName describe the app, so that when it binds back to the AM we
11979 // know that it's scheduled for a backup-agent operation.
11980 }
11981
11982 return true;
11983 }
11984
11985 // A backup agent has just come up
11986 public void backupAgentCreated(String agentPackageName, IBinder agent) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011987 if (DEBUG_BACKUP) Slog.v(TAG, "backupAgentCreated: " + agentPackageName
Christopher Tate181fafa2009-05-14 11:12:14 -070011988 + " = " + agent);
11989
11990 synchronized(this) {
11991 if (!agentPackageName.equals(mBackupAppName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011992 Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
Christopher Tate181fafa2009-05-14 11:12:14 -070011993 return;
11994 }
Dianne Hackborn06740692010-09-22 22:46:21 -070011995 }
Christopher Tate181fafa2009-05-14 11:12:14 -070011996
Dianne Hackborn06740692010-09-22 22:46:21 -070011997 long oldIdent = Binder.clearCallingIdentity();
11998 try {
11999 IBackupManager bm = IBackupManager.Stub.asInterface(
12000 ServiceManager.getService(Context.BACKUP_SERVICE));
12001 bm.agentConnected(agentPackageName, agent);
12002 } catch (RemoteException e) {
12003 // can't happen; the backup manager service is local
12004 } catch (Exception e) {
12005 Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
12006 e.printStackTrace();
12007 } finally {
12008 Binder.restoreCallingIdentity(oldIdent);
Christopher Tate181fafa2009-05-14 11:12:14 -070012009 }
12010 }
12011
12012 // done with this agent
12013 public void unbindBackupAgent(ApplicationInfo appInfo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012014 if (DEBUG_BACKUP) Slog.v(TAG, "unbindBackupAgent: " + appInfo);
Christopher Tate8a27f922009-06-26 11:49:18 -070012015 if (appInfo == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012016 Slog.w(TAG, "unbind backup agent for null app");
Christopher Tate8a27f922009-06-26 11:49:18 -070012017 return;
12018 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012019
12020 synchronized(this) {
Christopher Tate8a27f922009-06-26 11:49:18 -070012021 if (mBackupAppName == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012022 Slog.w(TAG, "Unbinding backup agent with no active backup");
Christopher Tate8a27f922009-06-26 11:49:18 -070012023 return;
12024 }
12025
Christopher Tate181fafa2009-05-14 11:12:14 -070012026 if (!mBackupAppName.equals(appInfo.packageName)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012027 Slog.e(TAG, "Unbind of " + appInfo + " but is not the current backup target");
Christopher Tate181fafa2009-05-14 11:12:14 -070012028 return;
12029 }
12030
Christopher Tate6fa95972009-06-05 18:43:55 -070012031 ProcessRecord proc = mBackupTarget.app;
12032 mBackupTarget = null;
12033 mBackupAppName = null;
12034
12035 // Not backing this app up any more; reset its OOM adjustment
12036 updateOomAdjLocked(proc);
12037
Christopher Tatec7b31e32009-06-10 15:49:30 -070012038 // If the app crashed during backup, 'thread' will be null here
12039 if (proc.thread != null) {
12040 try {
Dianne Hackborne2515ee2011-04-27 18:52:56 -040012041 proc.thread.scheduleDestroyBackupAgent(appInfo,
12042 compatibilityInfoForPackageLocked(appInfo));
Christopher Tatec7b31e32009-06-10 15:49:30 -070012043 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012044 Slog.e(TAG, "Exception when unbinding backup agent:");
Christopher Tatec7b31e32009-06-10 15:49:30 -070012045 e.printStackTrace();
12046 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012047 }
Christopher Tate181fafa2009-05-14 11:12:14 -070012048 }
12049 }
12050 // =========================================================
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012051 // BROADCASTS
12052 // =========================================================
12053
Josh Bartel7f208742010-02-25 11:01:44 -060012054 private final List getStickiesLocked(String action, IntentFilter filter,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012055 List cur) {
12056 final ContentResolver resolver = mContext.getContentResolver();
12057 final ArrayList<Intent> list = mStickyBroadcasts.get(action);
12058 if (list == null) {
12059 return cur;
12060 }
12061 int N = list.size();
12062 for (int i=0; i<N; i++) {
12063 Intent intent = list.get(i);
12064 if (filter.match(resolver, intent, true, TAG) >= 0) {
12065 if (cur == null) {
12066 cur = new ArrayList<Intent>();
12067 }
12068 cur.add(intent);
12069 }
12070 }
12071 return cur;
12072 }
12073
12074 private final void scheduleBroadcastsLocked() {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012075 if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts: current="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012076 + mBroadcastsScheduled);
12077
12078 if (mBroadcastsScheduled) {
12079 return;
12080 }
12081 mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
12082 mBroadcastsScheduled = true;
12083 }
12084
Dianne Hackborn6c418d52011-06-29 14:05:33 -070012085 public Intent registerReceiver(IApplicationThread caller, String callerPackage,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012086 IIntentReceiver receiver, IntentFilter filter, String permission) {
12087 synchronized(this) {
12088 ProcessRecord callerApp = null;
12089 if (caller != null) {
12090 callerApp = getRecordForAppLocked(caller);
12091 if (callerApp == null) {
12092 throw new SecurityException(
12093 "Unable to find app for caller " + caller
12094 + " (pid=" + Binder.getCallingPid()
12095 + ") when registering receiver " + receiver);
12096 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -070012097 if (callerApp.info.uid != Process.SYSTEM_UID &&
12098 !callerApp.pkgList.contains(callerPackage)) {
12099 throw new SecurityException("Given caller package " + callerPackage
12100 + " is not running in process " + callerApp);
12101 }
12102 } else {
12103 callerPackage = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012104 }
12105
12106 List allSticky = null;
12107
12108 // Look for any matching sticky broadcasts...
12109 Iterator actions = filter.actionsIterator();
12110 if (actions != null) {
12111 while (actions.hasNext()) {
12112 String action = (String)actions.next();
Josh Bartel7f208742010-02-25 11:01:44 -060012113 allSticky = getStickiesLocked(action, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012114 }
12115 } else {
Josh Bartel7f208742010-02-25 11:01:44 -060012116 allSticky = getStickiesLocked(null, filter, allSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012117 }
12118
12119 // The first sticky in the list is returned directly back to
12120 // the client.
12121 Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
12122
Joe Onorato8a9b2202010-02-26 18:56:32 -080012123 if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012124 + ": " + sticky);
12125
12126 if (receiver == null) {
12127 return sticky;
12128 }
12129
12130 ReceiverList rl
12131 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
12132 if (rl == null) {
12133 rl = new ReceiverList(this, callerApp,
12134 Binder.getCallingPid(),
12135 Binder.getCallingUid(), receiver);
12136 if (rl.app != null) {
12137 rl.app.receivers.add(rl);
12138 } else {
12139 try {
12140 receiver.asBinder().linkToDeath(rl, 0);
12141 } catch (RemoteException e) {
12142 return sticky;
12143 }
12144 rl.linkedToDeath = true;
12145 }
12146 mRegisteredReceivers.put(receiver.asBinder(), rl);
12147 }
Dianne Hackborn6c418d52011-06-29 14:05:33 -070012148 BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage, permission);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012149 rl.add(bf);
12150 if (!bf.debugCheck()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012151 Slog.w(TAG, "==> For Dynamic broadast");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012152 }
12153 mReceiverResolver.addFilter(bf);
12154
12155 // Enqueue broadcasts for all existing stickies that match
12156 // this filter.
12157 if (allSticky != null) {
12158 ArrayList receivers = new ArrayList();
12159 receivers.add(bf);
12160
12161 int N = allSticky.size();
12162 for (int i=0; i<N; i++) {
12163 Intent intent = (Intent)allSticky.get(i);
12164 BroadcastRecord r = new BroadcastRecord(intent, null,
12165 null, -1, -1, null, receivers, null, 0, null, null,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012166 false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012167 if (mParallelBroadcasts.size() == 0) {
12168 scheduleBroadcastsLocked();
12169 }
12170 mParallelBroadcasts.add(r);
12171 }
12172 }
12173
12174 return sticky;
12175 }
12176 }
12177
12178 public void unregisterReceiver(IIntentReceiver receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012179 if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012180
12181 boolean doNext = false;
12182
12183 synchronized(this) {
12184 ReceiverList rl
12185 = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
12186 if (rl != null) {
12187 if (rl.curBroadcast != null) {
12188 BroadcastRecord r = rl.curBroadcast;
12189 doNext = finishReceiverLocked(
12190 receiver.asBinder(), r.resultCode, r.resultData,
12191 r.resultExtras, r.resultAbort, true);
12192 }
12193
12194 if (rl.app != null) {
12195 rl.app.receivers.remove(rl);
12196 }
12197 removeReceiverLocked(rl);
12198 if (rl.linkedToDeath) {
12199 rl.linkedToDeath = false;
12200 rl.receiver.asBinder().unlinkToDeath(rl, 0);
12201 }
12202 }
12203 }
12204
12205 if (!doNext) {
12206 return;
12207 }
12208
12209 final long origId = Binder.clearCallingIdentity();
12210 processNextBroadcast(false);
12211 trimApplications();
12212 Binder.restoreCallingIdentity(origId);
12213 }
12214
12215 void removeReceiverLocked(ReceiverList rl) {
12216 mRegisteredReceivers.remove(rl.receiver.asBinder());
12217 int N = rl.size();
12218 for (int i=0; i<N; i++) {
12219 mReceiverResolver.removeFilter(rl.get(i));
12220 }
12221 }
12222
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070012223 private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
12224 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
12225 ProcessRecord r = mLruProcesses.get(i);
12226 if (r.thread != null) {
12227 try {
12228 r.thread.dispatchPackageBroadcast(cmd, packages);
12229 } catch (RemoteException ex) {
12230 }
12231 }
12232 }
12233 }
12234
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012235 private final int broadcastIntentLocked(ProcessRecord callerApp,
12236 String callerPackage, Intent intent, String resolvedType,
12237 IIntentReceiver resultTo, int resultCode, String resultData,
12238 Bundle map, String requiredPermission,
12239 boolean ordered, boolean sticky, int callingPid, int callingUid) {
12240 intent = new Intent(intent);
12241
Dianne Hackborne7f97212011-02-24 14:40:20 -080012242 // By default broadcasts do not go to stopped apps.
12243 intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
12244
Joe Onorato8a9b2202010-02-26 18:56:32 -080012245 if (DEBUG_BROADCAST_LIGHT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012246 TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
12247 + " ordered=" + ordered);
12248 if ((resultTo != null) && !ordered) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012249 Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012250 }
12251
12252 // Handle special intents: if this broadcast is from the package
12253 // manager about a package being removed, we need to remove all of
12254 // its activities from the history stack.
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070012255 final boolean uidRemoved = Intent.ACTION_UID_REMOVED.equals(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012256 intent.getAction());
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070012257 if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
12258 || Intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012259 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012260 || uidRemoved) {
12261 if (checkComponentPermission(
12262 android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080012263 callingPid, callingUid, -1, true)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012264 == PackageManager.PERMISSION_GRANTED) {
12265 if (uidRemoved) {
12266 final Bundle intentExtras = intent.getExtras();
12267 final int uid = intentExtras != null
12268 ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
12269 if (uid >= 0) {
12270 BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
12271 synchronized (bs) {
12272 bs.removeUidStatsLocked(uid);
12273 }
12274 }
12275 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012276 // If resources are unvailble just force stop all
12277 // those packages and flush the attribute cache as well.
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080012278 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012279 String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
12280 if (list != null && (list.length > 0)) {
12281 for (String pkg : list) {
Christopher Tate3dacd842011-08-19 14:56:15 -070012282 forceStopPackageLocked(pkg, -1, false, true, true, false);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012283 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070012284 sendPackageBroadcastLocked(
12285 IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012286 }
12287 } else {
12288 Uri data = intent.getData();
12289 String ssp;
12290 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
12291 if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
12292 forceStopPackageLocked(ssp,
Christopher Tate3dacd842011-08-19 14:56:15 -070012293 intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true, false);
Dianne Hackbornde7faf62009-06-30 13:27:30 -070012294 }
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070012295 if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
Dianne Hackborn4416c3d2010-05-04 17:22:49 -070012296 sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
12297 new String[] {ssp});
12298 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012299 }
12300 }
12301 }
12302 } else {
12303 String msg = "Permission Denial: " + intent.getAction()
12304 + " broadcast from " + callerPackage + " (pid=" + callingPid
12305 + ", uid=" + callingUid + ")"
12306 + " requires "
12307 + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012308 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012309 throw new SecurityException(msg);
12310 }
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070012311
12312 // Special case for adding a package: by default turn on compatibility
12313 // mode.
12314 } else if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())) {
Dianne Hackborn8ea5e1d2011-05-27 16:45:31 -070012315 Uri data = intent.getData();
12316 String ssp;
12317 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
12318 mCompatModePackages.handlePackageAddedLocked(ssp,
12319 intent.getBooleanExtra(Intent.EXTRA_REPLACING, false));
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070012320 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012321 }
12322
12323 /*
12324 * If this is the time zone changed action, queue up a message that will reset the timezone
12325 * of all currently running processes. This message will get queued up before the broadcast
12326 * happens.
12327 */
12328 if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
12329 mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
12330 }
12331
Robert Greenwalt03595d02010-11-02 14:08:23 -070012332 if (intent.ACTION_CLEAR_DNS_CACHE.equals(intent.getAction())) {
12333 mHandler.sendEmptyMessage(CLEAR_DNS_CACHE);
12334 }
12335
Robert Greenwalt434203a2010-10-11 16:00:27 -070012336 if (Proxy.PROXY_CHANGE_ACTION.equals(intent.getAction())) {
12337 ProxyProperties proxy = intent.getParcelableExtra("proxy");
12338 mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY, proxy));
12339 }
12340
Dianne Hackborn854060af2009-07-09 18:14:31 -070012341 /*
12342 * Prevent non-system code (defined here to be non-persistent
12343 * processes) from sending protected broadcasts.
12344 */
12345 if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID
12346 || callingUid == Process.SHELL_UID || callingUid == 0) {
12347 // Always okay.
12348 } else if (callerApp == null || !callerApp.persistent) {
12349 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012350 if (AppGlobals.getPackageManager().isProtectedBroadcast(
Dianne Hackborn854060af2009-07-09 18:14:31 -070012351 intent.getAction())) {
12352 String msg = "Permission Denial: not allowed to send broadcast "
12353 + intent.getAction() + " from pid="
12354 + callingPid + ", uid=" + callingUid;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012355 Slog.w(TAG, msg);
Dianne Hackborn854060af2009-07-09 18:14:31 -070012356 throw new SecurityException(msg);
12357 }
12358 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012359 Slog.w(TAG, "Remote exception", e);
Dianne Hackborn854060af2009-07-09 18:14:31 -070012360 return BROADCAST_SUCCESS;
12361 }
12362 }
12363
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012364 // Add to the sticky list if requested.
12365 if (sticky) {
12366 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
12367 callingPid, callingUid)
12368 != PackageManager.PERMISSION_GRANTED) {
12369 String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
12370 + callingPid + ", uid=" + callingUid
12371 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012372 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012373 throw new SecurityException(msg);
12374 }
12375 if (requiredPermission != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012376 Slog.w(TAG, "Can't broadcast sticky intent " + intent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012377 + " and enforce permission " + requiredPermission);
12378 return BROADCAST_STICKY_CANT_HAVE_PERMISSION;
12379 }
12380 if (intent.getComponent() != null) {
12381 throw new SecurityException(
12382 "Sticky broadcasts can't target a specific component");
12383 }
12384 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
12385 if (list == null) {
12386 list = new ArrayList<Intent>();
12387 mStickyBroadcasts.put(intent.getAction(), list);
12388 }
12389 int N = list.size();
12390 int i;
12391 for (i=0; i<N; i++) {
12392 if (intent.filterEquals(list.get(i))) {
12393 // This sticky already exists, replace it.
12394 list.set(i, new Intent(intent));
12395 break;
12396 }
12397 }
12398 if (i >= N) {
12399 list.add(new Intent(intent));
12400 }
12401 }
12402
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012403 // Figure out who all will receive this broadcast.
12404 List receivers = null;
12405 List<BroadcastFilter> registeredReceivers = null;
12406 try {
12407 if (intent.getComponent() != null) {
12408 // Broadcast is going to one specific receiver class...
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012409 ActivityInfo ai = AppGlobals.getPackageManager().
Dianne Hackborn1655be42009-05-08 14:29:01 -070012410 getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012411 if (ai != null) {
12412 receivers = new ArrayList();
12413 ResolveInfo ri = new ResolveInfo();
12414 ri.activityInfo = ai;
12415 receivers.add(ri);
12416 }
12417 } else {
12418 // Need to resolve the intent to interested receivers...
12419 if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
12420 == 0) {
12421 receivers =
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070012422 AppGlobals.getPackageManager().queryIntentReceivers(
Dianne Hackborn1655be42009-05-08 14:29:01 -070012423 intent, resolvedType, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012424 }
Mihai Preda074edef2009-05-18 17:13:31 +020012425 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012426 }
12427 } catch (RemoteException ex) {
12428 // pm is in same process, this will never happen.
12429 }
12430
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012431 final boolean replacePending =
12432 (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
12433
Joe Onorato8a9b2202010-02-26 18:56:32 -080012434 if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction()
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012435 + " replacePending=" + replacePending);
12436
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012437 int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
12438 if (!ordered && NR > 0) {
12439 // If we are not serializing this broadcast, then send the
12440 // registered receivers separately so they don't wait for the
12441 // components to be launched.
12442 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12443 callerPackage, callingPid, callingUid, requiredPermission,
12444 registeredReceivers, resultTo, resultCode, resultData, map,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012445 ordered, sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012446 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012447 TAG, "Enqueueing parallel broadcast " + r
12448 + ": prev had " + mParallelBroadcasts.size());
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012449 boolean replaced = false;
12450 if (replacePending) {
12451 for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
12452 if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012453 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012454 "***** DROPPING PARALLEL: " + intent);
12455 mParallelBroadcasts.set(i, r);
12456 replaced = true;
12457 break;
12458 }
12459 }
12460 }
12461 if (!replaced) {
12462 mParallelBroadcasts.add(r);
12463 scheduleBroadcastsLocked();
12464 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012465 registeredReceivers = null;
12466 NR = 0;
12467 }
12468
12469 // Merge into one list.
12470 int ir = 0;
12471 if (receivers != null) {
12472 // A special case for PACKAGE_ADDED: do not allow the package
12473 // being added to see this broadcast. This prevents them from
12474 // using this as a back door to get run as soon as they are
12475 // installed. Maybe in the future we want to have a special install
12476 // broadcast or such for apps, but we'd like to deliberately make
12477 // this decision.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012478 String skipPackages[] = null;
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070012479 if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
12480 || Intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
12481 || Intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012482 Uri data = intent.getData();
12483 if (data != null) {
12484 String pkgName = data.getSchemeSpecificPart();
12485 if (pkgName != null) {
12486 skipPackages = new String[] { pkgName };
12487 }
12488 }
Dianne Hackborn0f1de9a2011-05-11 17:34:49 -070012489 } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012490 skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
The Android Open Source Project10592532009-03-18 17:39:46 -070012491 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080012492 if (skipPackages != null && (skipPackages.length > 0)) {
12493 for (String skipPackage : skipPackages) {
12494 if (skipPackage != null) {
12495 int NT = receivers.size();
12496 for (int it=0; it<NT; it++) {
12497 ResolveInfo curt = (ResolveInfo)receivers.get(it);
12498 if (curt.activityInfo.packageName.equals(skipPackage)) {
12499 receivers.remove(it);
12500 it--;
12501 NT--;
12502 }
12503 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012504 }
12505 }
12506 }
12507
12508 int NT = receivers != null ? receivers.size() : 0;
12509 int it = 0;
12510 ResolveInfo curt = null;
12511 BroadcastFilter curr = null;
12512 while (it < NT && ir < NR) {
12513 if (curt == null) {
12514 curt = (ResolveInfo)receivers.get(it);
12515 }
12516 if (curr == null) {
12517 curr = registeredReceivers.get(ir);
12518 }
12519 if (curr.getPriority() >= curt.priority) {
12520 // Insert this broadcast record into the final list.
12521 receivers.add(it, curr);
12522 ir++;
12523 curr = null;
12524 it++;
12525 NT++;
12526 } else {
12527 // Skip to the next ResolveInfo in the final list.
12528 it++;
12529 curt = null;
12530 }
12531 }
12532 }
12533 while (ir < NR) {
12534 if (receivers == null) {
12535 receivers = new ArrayList();
12536 }
12537 receivers.add(registeredReceivers.get(ir));
12538 ir++;
12539 }
12540
12541 if ((receivers != null && receivers.size() > 0)
12542 || resultTo != null) {
12543 BroadcastRecord r = new BroadcastRecord(intent, callerApp,
12544 callerPackage, callingPid, callingUid, requiredPermission,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012545 receivers, resultTo, resultCode, resultData, map, ordered,
12546 sticky, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012547 if (DEBUG_BROADCAST) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012548 TAG, "Enqueueing ordered broadcast " + r
12549 + ": prev had " + mOrderedBroadcasts.size());
12550 if (DEBUG_BROADCAST) {
12551 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080012552 Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012553 }
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012554 boolean replaced = false;
12555 if (replacePending) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012556 for (int i=mOrderedBroadcasts.size()-1; i>0; i--) {
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012557 if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012558 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080012559 "***** DROPPING ORDERED: " + intent);
12560 mOrderedBroadcasts.set(i, r);
12561 replaced = true;
12562 break;
12563 }
12564 }
12565 }
12566 if (!replaced) {
12567 mOrderedBroadcasts.add(r);
12568 scheduleBroadcastsLocked();
12569 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012570 }
12571
12572 return BROADCAST_SUCCESS;
12573 }
12574
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012575 final Intent verifyBroadcastLocked(Intent intent) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012576 // Refuse possible leaked file descriptors
12577 if (intent != null && intent.hasFileDescriptors() == true) {
12578 throw new IllegalArgumentException("File descriptors passed in Intent");
12579 }
12580
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012581 int flags = intent.getFlags();
12582
12583 if (!mProcessesReady) {
12584 // if the caller really truly claims to know what they're doing, go
12585 // ahead and allow the broadcast without launching any receivers
12586 if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
12587 intent = new Intent(intent);
12588 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
12589 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
12590 Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
12591 + " before boot completion");
12592 throw new IllegalStateException("Cannot broadcast before boot completed");
12593 }
12594 }
12595
12596 if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
12597 throw new IllegalArgumentException(
12598 "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
12599 }
12600
12601 return intent;
12602 }
12603
12604 public final int broadcastIntent(IApplicationThread caller,
12605 Intent intent, String resolvedType, IIntentReceiver resultTo,
12606 int resultCode, String resultData, Bundle map,
12607 String requiredPermission, boolean serialized, boolean sticky) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012608 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012609 intent = verifyBroadcastLocked(intent);
Dianne Hackborn9acc0302009-08-25 00:27:12 -070012610
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012611 final ProcessRecord callerApp = getRecordForAppLocked(caller);
12612 final int callingPid = Binder.getCallingPid();
12613 final int callingUid = Binder.getCallingUid();
12614 final long origId = Binder.clearCallingIdentity();
12615 int res = broadcastIntentLocked(callerApp,
12616 callerApp != null ? callerApp.info.packageName : null,
12617 intent, resolvedType, resultTo,
12618 resultCode, resultData, map, requiredPermission, serialized,
12619 sticky, callingPid, callingUid);
12620 Binder.restoreCallingIdentity(origId);
12621 return res;
12622 }
12623 }
12624
12625 int broadcastIntentInPackage(String packageName, int uid,
12626 Intent intent, String resolvedType, IIntentReceiver resultTo,
12627 int resultCode, String resultData, Bundle map,
12628 String requiredPermission, boolean serialized, boolean sticky) {
12629 synchronized(this) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012630 intent = verifyBroadcastLocked(intent);
12631
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012632 final long origId = Binder.clearCallingIdentity();
12633 int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
12634 resultTo, resultCode, resultData, map, requiredPermission,
12635 serialized, sticky, -1, uid);
12636 Binder.restoreCallingIdentity(origId);
12637 return res;
12638 }
12639 }
12640
12641 public final void unbroadcastIntent(IApplicationThread caller,
12642 Intent intent) {
12643 // Refuse possible leaked file descriptors
12644 if (intent != null && intent.hasFileDescriptors() == true) {
12645 throw new IllegalArgumentException("File descriptors passed in Intent");
12646 }
12647
12648 synchronized(this) {
12649 if (checkCallingPermission(android.Manifest.permission.BROADCAST_STICKY)
12650 != PackageManager.PERMISSION_GRANTED) {
12651 String msg = "Permission Denial: unbroadcastIntent() from pid="
12652 + Binder.getCallingPid()
12653 + ", uid=" + Binder.getCallingUid()
12654 + " requires " + android.Manifest.permission.BROADCAST_STICKY;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012655 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012656 throw new SecurityException(msg);
12657 }
12658 ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());
12659 if (list != null) {
12660 int N = list.size();
12661 int i;
12662 for (i=0; i<N; i++) {
12663 if (intent.filterEquals(list.get(i))) {
12664 list.remove(i);
12665 break;
12666 }
12667 }
12668 }
12669 }
12670 }
12671
12672 private final boolean finishReceiverLocked(IBinder receiver, int resultCode,
12673 String resultData, Bundle resultExtras, boolean resultAbort,
12674 boolean explicit) {
12675 if (mOrderedBroadcasts.size() == 0) {
12676 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012677 Slog.w(TAG, "finishReceiver called but no pending broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012678 }
12679 return false;
12680 }
12681 BroadcastRecord r = mOrderedBroadcasts.get(0);
12682 if (r.receiver == null) {
12683 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012684 Slog.w(TAG, "finishReceiver called but none active");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012685 }
12686 return false;
12687 }
12688 if (r.receiver != receiver) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012689 Slog.w(TAG, "finishReceiver called but active receiver is different");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012690 return false;
12691 }
12692 int state = r.state;
Dianne Hackbornce86ba82011-07-13 19:33:41 -070012693 r.state = BroadcastRecord.IDLE;
12694 if (state == BroadcastRecord.IDLE) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012695 if (explicit) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012696 Slog.w(TAG, "finishReceiver called but state is IDLE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012697 }
12698 }
12699 r.receiver = null;
12700 r.intent.setComponent(null);
12701 if (r.curApp != null) {
12702 r.curApp.curReceiver = null;
12703 }
12704 if (r.curFilter != null) {
12705 r.curFilter.receiverList.curBroadcast = null;
12706 }
12707 r.curFilter = null;
12708 r.curApp = null;
12709 r.curComponent = null;
12710 r.curReceiver = null;
12711 mPendingBroadcast = null;
12712
12713 r.resultCode = resultCode;
12714 r.resultData = resultData;
12715 r.resultExtras = resultExtras;
12716 r.resultAbort = resultAbort;
12717
12718 // We will process the next receiver right now if this is finishing
12719 // an app receiver (which is always asynchronous) or after we have
12720 // come back from calling a receiver.
12721 return state == BroadcastRecord.APP_RECEIVE
12722 || state == BroadcastRecord.CALL_DONE_RECEIVE;
12723 }
12724
12725 public void finishReceiver(IBinder who, int resultCode, String resultData,
12726 Bundle resultExtras, boolean resultAbort) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012727 if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012728
12729 // Refuse possible leaked file descriptors
12730 if (resultExtras != null && resultExtras.hasFileDescriptors()) {
12731 throw new IllegalArgumentException("File descriptors passed in Bundle");
12732 }
12733
12734 boolean doNext;
12735
12736 final long origId = Binder.clearCallingIdentity();
12737
12738 synchronized(this) {
12739 doNext = finishReceiverLocked(
12740 who, resultCode, resultData, resultExtras, resultAbort, true);
12741 }
12742
12743 if (doNext) {
12744 processNextBroadcast(false);
12745 }
12746 trimApplications();
12747
12748 Binder.restoreCallingIdentity(origId);
12749 }
12750
Jeff Brown4d94a762010-09-23 11:33:28 -070012751 private final void logBroadcastReceiverDiscardLocked(BroadcastRecord r) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012752 if (r.nextReceiver > 0) {
12753 Object curReceiver = r.receivers.get(r.nextReceiver-1);
12754 if (curReceiver instanceof BroadcastFilter) {
12755 BroadcastFilter bf = (BroadcastFilter) curReceiver;
Doug Zongker2bec3d42009-12-04 12:52:44 -080012756 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012757 System.identityHashCode(r),
12758 r.intent.getAction(),
12759 r.nextReceiver - 1,
12760 System.identityHashCode(bf));
12761 } else {
Doug Zongker2bec3d42009-12-04 12:52:44 -080012762 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012763 System.identityHashCode(r),
12764 r.intent.getAction(),
12765 r.nextReceiver - 1,
12766 ((ResolveInfo)curReceiver).toString());
12767 }
12768 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012769 Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012770 + r);
Doug Zongker2bec3d42009-12-04 12:52:44 -080012771 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012772 System.identityHashCode(r),
12773 r.intent.getAction(),
12774 r.nextReceiver,
12775 "NONE");
12776 }
12777 }
12778
Jeff Brown4d94a762010-09-23 11:33:28 -070012779 private final void setBroadcastTimeoutLocked(long timeoutTime) {
12780 if (! mPendingBroadcastTimeoutMessage) {
12781 Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
12782 mHandler.sendMessageAtTime(msg, timeoutTime);
12783 mPendingBroadcastTimeoutMessage = true;
12784 }
12785 }
12786
12787 private final void cancelBroadcastTimeoutLocked() {
12788 if (mPendingBroadcastTimeoutMessage) {
12789 mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
12790 mPendingBroadcastTimeoutMessage = false;
12791 }
12792 }
12793
12794 private final void broadcastTimeoutLocked(boolean fromMsg) {
12795 if (fromMsg) {
12796 mPendingBroadcastTimeoutMessage = false;
12797 }
12798
12799 if (mOrderedBroadcasts.size() == 0) {
12800 return;
12801 }
12802
12803 long now = SystemClock.uptimeMillis();
12804 BroadcastRecord r = mOrderedBroadcasts.get(0);
12805 if (fromMsg) {
12806 if (mDidDexOpt) {
12807 // Delay timeouts until dexopt finishes.
12808 mDidDexOpt = false;
12809 long timeoutTime = SystemClock.uptimeMillis() + BROADCAST_TIMEOUT;
12810 setBroadcastTimeoutLocked(timeoutTime);
12811 return;
12812 }
12813 if (! mProcessesReady) {
12814 // Only process broadcast timeouts if the system is ready. That way
12815 // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
12816 // to do heavy lifting for system up.
12817 return;
12818 }
12819
12820 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
12821 if (timeoutTime > now) {
12822 // We can observe premature timeouts because we do not cancel and reset the
12823 // broadcast timeout message after each receiver finishes. Instead, we set up
12824 // an initial timeout then kick it down the road a little further as needed
12825 // when it expires.
12826 if (DEBUG_BROADCAST) Slog.v(TAG,
12827 "Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
12828 + timeoutTime);
12829 setBroadcastTimeoutLocked(timeoutTime);
12830 return;
12831 }
12832 }
12833
12834 Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver
12835 + ", started " + (now - r.receiverTime) + "ms ago");
12836 r.receiverTime = now;
12837 r.anrCount++;
12838
12839 // Current receiver has passed its expiration date.
12840 if (r.nextReceiver <= 0) {
12841 Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
12842 return;
12843 }
12844
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012845 ProcessRecord app = null;
12846 String anrMessage = null;
12847
Jeff Brown4d94a762010-09-23 11:33:28 -070012848 Object curReceiver = r.receivers.get(r.nextReceiver-1);
12849 Slog.w(TAG, "Receiver during timeout: " + curReceiver);
12850 logBroadcastReceiverDiscardLocked(r);
12851 if (curReceiver instanceof BroadcastFilter) {
12852 BroadcastFilter bf = (BroadcastFilter)curReceiver;
12853 if (bf.receiverList.pid != 0
12854 && bf.receiverList.pid != MY_PID) {
12855 synchronized (this.mPidsSelfLocked) {
12856 app = this.mPidsSelfLocked.get(
12857 bf.receiverList.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012858 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012859 }
Jeff Brown4d94a762010-09-23 11:33:28 -070012860 } else {
12861 app = r.curApp;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012862 }
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012863
Jeff Brown4d94a762010-09-23 11:33:28 -070012864 if (app != null) {
12865 anrMessage = "Broadcast of " + r.intent.toString();
12866 }
12867
12868 if (mPendingBroadcast == r) {
12869 mPendingBroadcast = null;
12870 }
12871
12872 // Move on to the next receiver.
12873 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
12874 r.resultExtras, r.resultAbort, true);
12875 scheduleBroadcastsLocked();
12876
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012877 if (anrMessage != null) {
Jeff Brown4d94a762010-09-23 11:33:28 -070012878 // Post the ANR to the handler since we do not want to process ANRs while
12879 // potentially holding our lock.
12880 mHandler.post(new AppNotResponding(app, anrMessage));
Dianne Hackbornad5499d2010-03-29 18:08:45 -070012881 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012882 }
12883
12884 private final void processCurBroadcastLocked(BroadcastRecord r,
12885 ProcessRecord app) throws RemoteException {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012886 if (DEBUG_BROADCAST) Slog.v(TAG,
12887 "Process cur broadcast " + r + " for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012888 if (app.thread == null) {
12889 throw new RemoteException();
12890 }
12891 r.receiver = app.thread.asBinder();
12892 r.curApp = app;
12893 app.curReceiver = r;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080012894 updateLruProcessLocked(app, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012895
12896 // Tell the application to launch this receiver.
12897 r.intent.setComponent(r.curComponent);
12898
12899 boolean started = false;
12900 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012901 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012902 "Delivering to component " + r.curComponent
12903 + ": " + r);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -070012904 ensurePackageDexOpt(r.intent.getComponent().getPackageName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012905 app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
Dianne Hackborne2515ee2011-04-27 18:52:56 -040012906 compatibilityInfoForPackageLocked(r.curReceiver.applicationInfo),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012907 r.resultCode, r.resultData, r.resultExtras, r.ordered);
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012908 if (DEBUG_BROADCAST) Slog.v(TAG,
12909 "Process cur broadcast " + r + " DELIVERED for app " + app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012910 started = true;
12911 } finally {
12912 if (!started) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070012913 if (DEBUG_BROADCAST) Slog.v(TAG,
12914 "Process cur broadcast " + r + ": NOT STARTED!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012915 r.receiver = null;
12916 r.curApp = null;
12917 app.curReceiver = null;
12918 }
12919 }
12920
12921 }
12922
Jeff Brown4d94a762010-09-23 11:33:28 -070012923 static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012924 Intent intent, int resultCode, String data, Bundle extras,
12925 boolean ordered, boolean sticky) throws RemoteException {
Jeff Brown4d94a762010-09-23 11:33:28 -070012926 // Send the intent to the receiver asynchronously using one-way binder calls.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012927 if (app != null && app.thread != null) {
12928 // If we have an app thread, do the call through that so it is
12929 // correctly ordered with other one-way calls.
12930 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012931 data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012932 } else {
Dianne Hackborn68d881c2009-10-05 13:58:17 -070012933 receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012934 }
12935 }
12936
Jeff Brown4d94a762010-09-23 11:33:28 -070012937 private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012938 BroadcastFilter filter, boolean ordered) {
12939 boolean skip = false;
12940 if (filter.requiredPermission != null) {
12941 int perm = checkComponentPermission(filter.requiredPermission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080012942 r.callingPid, r.callingUid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012943 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012944 Slog.w(TAG, "Permission Denial: broadcasting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012945 + r.intent.toString()
12946 + " from " + r.callerPackage + " (pid="
12947 + r.callingPid + ", uid=" + r.callingUid + ")"
12948 + " requires " + filter.requiredPermission
12949 + " due to registered receiver " + filter);
12950 skip = true;
12951 }
12952 }
12953 if (r.requiredPermission != null) {
12954 int perm = checkComponentPermission(r.requiredPermission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080012955 filter.receiverList.pid, filter.receiverList.uid, -1, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012956 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012957 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012958 + r.intent.toString()
12959 + " to " + filter.receiverList.app
12960 + " (pid=" + filter.receiverList.pid
12961 + ", uid=" + filter.receiverList.uid + ")"
12962 + " requires " + r.requiredPermission
12963 + " due to sender " + r.callerPackage
12964 + " (uid " + r.callingUid + ")");
12965 skip = true;
12966 }
12967 }
12968
12969 if (!skip) {
12970 // If this is not being sent as an ordered broadcast, then we
12971 // don't want to touch the fields that keep track of the current
12972 // state of ordered broadcasts.
12973 if (ordered) {
12974 r.receiver = filter.receiverList.receiver.asBinder();
12975 r.curFilter = filter;
12976 filter.receiverList.curBroadcast = r;
12977 r.state = BroadcastRecord.CALL_IN_RECEIVE;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012978 if (filter.receiverList.app != null) {
12979 // Bump hosting application to no longer be in background
12980 // scheduling class. Note that we can't do that if there
12981 // isn't an app... but we can only be in that case for
12982 // things that directly call the IActivityManager API, which
12983 // are already core system stuff so don't matter for this.
12984 r.curApp = filter.receiverList.app;
12985 filter.receiverList.app.curReceiver = r;
12986 updateOomAdjLocked();
12987 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012988 }
12989 try {
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012990 if (DEBUG_BROADCAST_LIGHT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012991 int seq = r.intent.getIntExtra("seq", -1);
Dianne Hackborn399cccb2010-04-13 22:57:49 -070012992 Slog.i(TAG, "Delivering to " + filter
Dianne Hackborn82f3f002009-06-16 18:49:05 -070012993 + " (seq=" + seq + "): " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012994 }
Jeff Brown4d94a762010-09-23 11:33:28 -070012995 performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012996 new Intent(r.intent), r.resultCode,
Dianne Hackborn12527f92009-11-11 17:39:50 -080012997 r.resultData, r.resultExtras, r.ordered, r.initialSticky);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012998 if (ordered) {
12999 r.state = BroadcastRecord.CALL_DONE_RECEIVE;
13000 }
13001 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013002 Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013003 if (ordered) {
13004 r.receiver = null;
13005 r.curFilter = null;
13006 filter.receiverList.curBroadcast = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013007 if (filter.receiverList.app != null) {
13008 filter.receiverList.app.curReceiver = null;
13009 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013010 }
13011 }
13012 }
13013 }
13014
Dianne Hackborn12527f92009-11-11 17:39:50 -080013015 private final void addBroadcastToHistoryLocked(BroadcastRecord r) {
13016 if (r.callingUid < 0) {
13017 // This was from a registerReceiver() call; ignore it.
13018 return;
13019 }
13020 System.arraycopy(mBroadcastHistory, 0, mBroadcastHistory, 1,
13021 MAX_BROADCAST_HISTORY-1);
13022 r.finishTime = SystemClock.uptimeMillis();
13023 mBroadcastHistory[0] = r;
13024 }
13025
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013026 private final void processNextBroadcast(boolean fromMsg) {
13027 synchronized(this) {
13028 BroadcastRecord r;
13029
Joe Onorato8a9b2202010-02-26 18:56:32 -080013030 if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013031 + mParallelBroadcasts.size() + " broadcasts, "
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013032 + mOrderedBroadcasts.size() + " ordered broadcasts");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013033
13034 updateCpuStats();
13035
13036 if (fromMsg) {
13037 mBroadcastsScheduled = false;
13038 }
13039
13040 // First, deliver any non-serialized broadcasts right away.
13041 while (mParallelBroadcasts.size() > 0) {
13042 r = mParallelBroadcasts.remove(0);
Dianne Hackborn12527f92009-11-11 17:39:50 -080013043 r.dispatchTime = SystemClock.uptimeMillis();
Dianne Hackbornd99b2932011-08-18 14:39:58 -070013044 r.dispatchClockTime = System.currentTimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013045 final int N = r.receivers.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -080013046 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013047 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013048 for (int i=0; i<N; i++) {
13049 Object target = r.receivers.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013050 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013051 "Delivering non-ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013052 + target + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070013053 deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013054 }
Dianne Hackborn12527f92009-11-11 17:39:50 -080013055 addBroadcastToHistoryLocked(r);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013056 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013057 + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013058 }
13059
13060 // Now take care of the next serialized one...
13061
13062 // If we are waiting for a process to come up to handle the next
13063 // broadcast, then do nothing at this point. Just in case, we
13064 // check that the process we're waiting for still exists.
13065 if (mPendingBroadcast != null) {
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070013066 if (DEBUG_BROADCAST_LIGHT) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013067 Slog.v(TAG, "processNextBroadcast: waiting for "
Dianne Hackbornbd0a81f2009-10-04 13:30:50 -070013068 + mPendingBroadcast.curApp);
13069 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013070
13071 boolean isDead;
13072 synchronized (mPidsSelfLocked) {
13073 isDead = (mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
13074 }
13075 if (!isDead) {
13076 // It's still alive, so keep waiting
13077 return;
13078 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013079 Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013080 + " died before responding to broadcast");
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070013081 mPendingBroadcast.state = BroadcastRecord.IDLE;
13082 mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013083 mPendingBroadcast = null;
13084 }
13085 }
13086
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013087 boolean looped = false;
13088
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013089 do {
13090 if (mOrderedBroadcasts.size() == 0) {
13091 // No more broadcasts pending, so all done!
13092 scheduleAppGcsLocked();
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013093 if (looped) {
13094 // If we had finished the last ordered broadcast, then
13095 // make sure all processes have correct oom and sched
13096 // adjustments.
13097 updateOomAdjLocked();
13098 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013099 return;
13100 }
13101 r = mOrderedBroadcasts.get(0);
13102 boolean forceReceive = false;
13103
13104 // Ensure that even if something goes awry with the timeout
13105 // detection, we catch "hung" broadcasts here, discard them,
Jeff Hamiltonacf84742010-05-25 22:10:18 -050013106 // and continue to make progress.
13107 //
13108 // This is only done if the system is ready so that PRE_BOOT_COMPLETED
Jeff Brown4d94a762010-09-23 11:33:28 -070013109 // receivers don't get executed with timeouts. They're intended for
Jeff Hamiltonacf84742010-05-25 22:10:18 -050013110 // one time heavy lifting after system upgrades and can take
13111 // significant amounts of time.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013112 int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070013113 if (mProcessesReady && r.dispatchTime > 0) {
Jeff Hamiltonacf84742010-05-25 22:10:18 -050013114 long now = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013115 if ((numReceivers > 0) &&
13116 (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013117 Slog.w(TAG, "Hung broadcast discarded after timeout failure:"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013118 + " now=" + now
13119 + " dispatchTime=" + r.dispatchTime
Dianne Hackborn12527f92009-11-11 17:39:50 -080013120 + " startTime=" + r.receiverTime
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013121 + " intent=" + r.intent
13122 + " numReceivers=" + numReceivers
13123 + " nextReceiver=" + r.nextReceiver
13124 + " state=" + r.state);
Jeff Brown4d94a762010-09-23 11:33:28 -070013125 broadcastTimeoutLocked(false); // forcibly finish this broadcast
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013126 forceReceive = true;
13127 r.state = BroadcastRecord.IDLE;
13128 }
13129 }
13130
13131 if (r.state != BroadcastRecord.IDLE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013132 if (DEBUG_BROADCAST) Slog.d(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013133 "processNextBroadcast() called when not idle (state="
13134 + r.state + ")");
13135 return;
13136 }
13137
13138 if (r.receivers == null || r.nextReceiver >= numReceivers
13139 || r.resultAbort || forceReceive) {
13140 // No more receivers for this broadcast! Send the final
13141 // result if requested...
13142 if (r.resultTo != null) {
13143 try {
13144 if (DEBUG_BROADCAST) {
13145 int seq = r.intent.getIntExtra("seq", -1);
Joe Onorato8a9b2202010-02-26 18:56:32 -080013146 Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013147 + " seq=" + seq + " app=" + r.callerApp);
13148 }
Jeff Brown4d94a762010-09-23 11:33:28 -070013149 performReceiveLocked(r.callerApp, r.resultTo,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013150 new Intent(r.intent), r.resultCode,
Dianne Hackborn68d881c2009-10-05 13:58:17 -070013151 r.resultData, r.resultExtras, false, false);
Johannes Carlssonb5a86542010-10-27 10:08:10 +020013152 // Set this to null so that the reference
13153 // (local and remote) isnt kept in the mBroadcastHistory.
13154 r.resultTo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013155 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013156 Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013157 }
13158 }
13159
Joe Onorato8a9b2202010-02-26 18:56:32 -080013160 if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
Jeff Brown4d94a762010-09-23 11:33:28 -070013161 cancelBroadcastTimeoutLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013162
Joe Onorato8a9b2202010-02-26 18:56:32 -080013163 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013164 + r);
13165
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013166 // ... and on to the next...
Dianne Hackborn12527f92009-11-11 17:39:50 -080013167 addBroadcastToHistoryLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013168 mOrderedBroadcasts.remove(0);
13169 r = null;
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013170 looped = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013171 continue;
13172 }
13173 } while (r == null);
13174
13175 // Get the next receiver...
13176 int recIdx = r.nextReceiver++;
13177
13178 // Keep track of when this receiver started, and make sure there
13179 // is a timeout message pending to kill it if need be.
Dianne Hackborn12527f92009-11-11 17:39:50 -080013180 r.receiverTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013181 if (recIdx == 0) {
Dianne Hackborn12527f92009-11-11 17:39:50 -080013182 r.dispatchTime = r.receiverTime;
Dianne Hackbornd99b2932011-08-18 14:39:58 -070013183 r.dispatchClockTime = System.currentTimeMillis();
Joe Onorato8a9b2202010-02-26 18:56:32 -080013184 if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
Dianne Hackborn82f3f002009-06-16 18:49:05 -070013185 + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070013186 }
13187 if (! mPendingBroadcastTimeoutMessage) {
13188 long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013189 if (DEBUG_BROADCAST) Slog.v(TAG,
Jeff Brown4d94a762010-09-23 11:33:28 -070013190 "Submitting BROADCAST_TIMEOUT_MSG for " + r + " at " + timeoutTime);
13191 setBroadcastTimeoutLocked(timeoutTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013192 }
13193
13194 Object nextReceiver = r.receivers.get(recIdx);
13195 if (nextReceiver instanceof BroadcastFilter) {
13196 // Simple case: this is a registered receiver who gets
13197 // a direct call.
13198 BroadcastFilter filter = (BroadcastFilter)nextReceiver;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013199 if (DEBUG_BROADCAST) Slog.v(TAG,
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013200 "Delivering ordered to registered "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013201 + filter + ": " + r);
Jeff Brown4d94a762010-09-23 11:33:28 -070013202 deliverToRegisteredReceiverLocked(r, filter, r.ordered);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013203 if (r.receiver == null || !r.ordered) {
13204 // The receiver has already finished, so schedule to
13205 // process the next one.
Dianne Hackborn399cccb2010-04-13 22:57:49 -070013206 if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing: ordered="
13207 + r.ordered + " receiver=" + r.receiver);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013208 r.state = BroadcastRecord.IDLE;
13209 scheduleBroadcastsLocked();
13210 }
13211 return;
13212 }
13213
13214 // Hard case: need to instantiate the receiver, possibly
13215 // starting its application process to host it.
13216
13217 ResolveInfo info =
13218 (ResolveInfo)nextReceiver;
13219
13220 boolean skip = false;
13221 int perm = checkComponentPermission(info.activityInfo.permission,
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080013222 r.callingPid, r.callingUid, info.activityInfo.applicationInfo.uid,
13223 info.activityInfo.exported);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013224 if (perm != PackageManager.PERMISSION_GRANTED) {
Dianne Hackborn6c2c5fc2011-01-18 17:02:33 -080013225 if (!info.activityInfo.exported) {
13226 Slog.w(TAG, "Permission Denial: broadcasting "
13227 + r.intent.toString()
13228 + " from " + r.callerPackage + " (pid=" + r.callingPid
13229 + ", uid=" + r.callingUid + ")"
13230 + " is not exported from uid " + info.activityInfo.applicationInfo.uid
13231 + " due to receiver " + info.activityInfo.packageName
13232 + "/" + info.activityInfo.name);
13233 } else {
13234 Slog.w(TAG, "Permission Denial: broadcasting "
13235 + r.intent.toString()
13236 + " from " + r.callerPackage + " (pid=" + r.callingPid
13237 + ", uid=" + r.callingUid + ")"
13238 + " requires " + info.activityInfo.permission
13239 + " due to receiver " + info.activityInfo.packageName
13240 + "/" + info.activityInfo.name);
13241 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013242 skip = true;
13243 }
Dianne Hackbornd99b2932011-08-18 14:39:58 -070013244 if (info.activityInfo.applicationInfo.uid != Process.SYSTEM_UID &&
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013245 r.requiredPermission != null) {
13246 try {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070013247 perm = AppGlobals.getPackageManager().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013248 checkPermission(r.requiredPermission,
13249 info.activityInfo.applicationInfo.packageName);
13250 } catch (RemoteException e) {
13251 perm = PackageManager.PERMISSION_DENIED;
13252 }
13253 if (perm != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013254 Slog.w(TAG, "Permission Denial: receiving "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013255 + r.intent + " to "
13256 + info.activityInfo.applicationInfo.packageName
13257 + " requires " + r.requiredPermission
13258 + " due to sender " + r.callerPackage
13259 + " (uid " + r.callingUid + ")");
13260 skip = true;
13261 }
13262 }
13263 if (r.curApp != null && r.curApp.crashing) {
13264 // If the target process is crashing, just skip it.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070013265 if (DEBUG_BROADCAST) Slog.v(TAG,
13266 "Skipping deliver ordered " + r + " to " + r.curApp
13267 + ": process crashing");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013268 skip = true;
13269 }
13270
13271 if (skip) {
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070013272 if (DEBUG_BROADCAST) Slog.v(TAG,
13273 "Skipping delivery of ordered " + r + " for whatever reason");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013274 r.receiver = null;
13275 r.curFilter = null;
13276 r.state = BroadcastRecord.IDLE;
13277 scheduleBroadcastsLocked();
13278 return;
13279 }
13280
13281 r.state = BroadcastRecord.APP_RECEIVE;
13282 String targetProcess = info.activityInfo.processName;
13283 r.curComponent = new ComponentName(
13284 info.activityInfo.applicationInfo.packageName,
13285 info.activityInfo.name);
13286 r.curReceiver = info.activityInfo;
13287
Dianne Hackborne7f97212011-02-24 14:40:20 -080013288 // Broadcast is being executed, its package can't be stopped.
13289 try {
13290 AppGlobals.getPackageManager().setPackageStoppedState(
13291 r.curComponent.getPackageName(), false);
13292 } catch (RemoteException e) {
Dianne Hackborna925cd42011-03-10 13:18:20 -080013293 } catch (IllegalArgumentException e) {
13294 Slog.w(TAG, "Failed trying to unstop package "
13295 + r.curComponent.getPackageName() + ": " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -080013296 }
13297
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013298 // Is this receiver's application already running?
13299 ProcessRecord app = getProcessRecordLocked(targetProcess,
13300 info.activityInfo.applicationInfo.uid);
13301 if (app != null && app.thread != null) {
13302 try {
Dianne Hackborn6c418d52011-06-29 14:05:33 -070013303 app.addPackage(info.activityInfo.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013304 processCurBroadcastLocked(r, app);
13305 return;
13306 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013307 Slog.w(TAG, "Exception when sending broadcast to "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013308 + r.curComponent, e);
13309 }
13310
13311 // If a dead object exception was thrown -- fall through to
13312 // restart the application.
13313 }
13314
Dianne Hackborn9acc0302009-08-25 00:27:12 -070013315 // Not running -- get it started, to be executed when the app comes up.
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070013316 if (DEBUG_BROADCAST) Slog.v(TAG,
13317 "Need to start app " + targetProcess + " for broadcast " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013318 if ((r.curApp=startProcessLocked(targetProcess,
13319 info.activityInfo.applicationInfo, true,
13320 r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
Dianne Hackborn9acc0302009-08-25 00:27:12 -070013321 "broadcast", r.curComponent,
13322 (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0))
13323 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013324 // Ah, this recipient is unavailable. Finish it if necessary,
13325 // and mark the broadcast record as ready for the next.
Joe Onorato8a9b2202010-02-26 18:56:32 -080013326 Slog.w(TAG, "Unable to launch app "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013327 + info.activityInfo.applicationInfo.packageName + "/"
13328 + info.activityInfo.applicationInfo.uid + " for broadcast "
13329 + r.intent + ": process is bad");
Jeff Brown4d94a762010-09-23 11:33:28 -070013330 logBroadcastReceiverDiscardLocked(r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013331 finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
13332 r.resultExtras, r.resultAbort, true);
13333 scheduleBroadcastsLocked();
13334 r.state = BroadcastRecord.IDLE;
13335 return;
13336 }
13337
13338 mPendingBroadcast = r;
Dianne Hackborn8891fdc2010-09-20 20:44:46 -070013339 mPendingBroadcastRecvIndex = recIdx;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013340 }
13341 }
13342
13343 // =========================================================
13344 // INSTRUMENTATION
13345 // =========================================================
13346
13347 public boolean startInstrumentation(ComponentName className,
13348 String profileFile, int flags, Bundle arguments,
13349 IInstrumentationWatcher watcher) {
13350 // Refuse possible leaked file descriptors
13351 if (arguments != null && arguments.hasFileDescriptors()) {
13352 throw new IllegalArgumentException("File descriptors passed in Bundle");
13353 }
13354
13355 synchronized(this) {
13356 InstrumentationInfo ii = null;
13357 ApplicationInfo ai = null;
13358 try {
13359 ii = mContext.getPackageManager().getInstrumentationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013360 className, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013361 ai = mContext.getPackageManager().getApplicationInfo(
Dianne Hackborn1655be42009-05-08 14:29:01 -070013362 ii.targetPackage, STOCK_PM_FLAGS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013363 } catch (PackageManager.NameNotFoundException e) {
13364 }
13365 if (ii == null) {
13366 reportStartInstrumentationFailure(watcher, className,
13367 "Unable to find instrumentation info for: " + className);
13368 return false;
13369 }
13370 if (ai == null) {
13371 reportStartInstrumentationFailure(watcher, className,
13372 "Unable to find instrumentation target package: " + ii.targetPackage);
13373 return false;
13374 }
13375
13376 int match = mContext.getPackageManager().checkSignatures(
13377 ii.targetPackage, ii.packageName);
13378 if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) {
13379 String msg = "Permission Denial: starting instrumentation "
13380 + className + " from pid="
13381 + Binder.getCallingPid()
13382 + ", uid=" + Binder.getCallingPid()
13383 + " not allowed because package " + ii.packageName
13384 + " does not have a signature matching the target "
13385 + ii.targetPackage;
13386 reportStartInstrumentationFailure(watcher, className, msg);
13387 throw new SecurityException(msg);
13388 }
13389
13390 final long origId = Binder.clearCallingIdentity();
Christopher Tate3dacd842011-08-19 14:56:15 -070013391 // Instrumentation can kill and relaunch even persistent processes
13392 forceStopPackageLocked(ii.targetPackage, -1, true, false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013393 ProcessRecord app = addAppLocked(ai);
13394 app.instrumentationClass = className;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013395 app.instrumentationInfo = ai;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013396 app.instrumentationProfileFile = profileFile;
13397 app.instrumentationArguments = arguments;
13398 app.instrumentationWatcher = watcher;
13399 app.instrumentationResultClass = className;
13400 Binder.restoreCallingIdentity(origId);
13401 }
13402
13403 return true;
13404 }
13405
13406 /**
13407 * Report errors that occur while attempting to start Instrumentation. Always writes the
13408 * error to the logs, but if somebody is watching, send the report there too. This enables
13409 * the "am" command to report errors with more information.
13410 *
13411 * @param watcher The IInstrumentationWatcher. Null if there isn't one.
13412 * @param cn The component name of the instrumentation.
13413 * @param report The error report.
13414 */
13415 private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
13416 ComponentName cn, String report) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013417 Slog.w(TAG, report);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013418 try {
13419 if (watcher != null) {
13420 Bundle results = new Bundle();
13421 results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
13422 results.putString("Error", report);
13423 watcher.instrumentationStatus(cn, -1, results);
13424 }
13425 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013426 Slog.w(TAG, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013427 }
13428 }
13429
13430 void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
13431 if (app.instrumentationWatcher != null) {
13432 try {
13433 // NOTE: IInstrumentationWatcher *must* be oneway here
13434 app.instrumentationWatcher.instrumentationFinished(
13435 app.instrumentationClass,
13436 resultCode,
13437 results);
13438 } catch (RemoteException e) {
13439 }
13440 }
13441 app.instrumentationWatcher = null;
13442 app.instrumentationClass = null;
Dianne Hackborn1655be42009-05-08 14:29:01 -070013443 app.instrumentationInfo = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013444 app.instrumentationProfileFile = null;
13445 app.instrumentationArguments = null;
13446
Christopher Tate3dacd842011-08-19 14:56:15 -070013447 forceStopPackageLocked(app.processName, -1, false, false, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013448 }
13449
13450 public void finishInstrumentation(IApplicationThread target,
13451 int resultCode, Bundle results) {
13452 // Refuse possible leaked file descriptors
13453 if (results != null && results.hasFileDescriptors()) {
13454 throw new IllegalArgumentException("File descriptors passed in Intent");
13455 }
13456
13457 synchronized(this) {
13458 ProcessRecord app = getRecordForAppLocked(target);
13459 if (app == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013460 Slog.w(TAG, "finishInstrumentation: no app for " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013461 return;
13462 }
13463 final long origId = Binder.clearCallingIdentity();
13464 finishInstrumentationLocked(app, resultCode, results);
13465 Binder.restoreCallingIdentity(origId);
13466 }
13467 }
13468
13469 // =========================================================
13470 // CONFIGURATION
13471 // =========================================================
13472
13473 public ConfigurationInfo getDeviceConfigurationInfo() {
13474 ConfigurationInfo config = new ConfigurationInfo();
13475 synchronized (this) {
13476 config.reqTouchScreen = mConfiguration.touchscreen;
13477 config.reqKeyboardType = mConfiguration.keyboard;
13478 config.reqNavigation = mConfiguration.navigation;
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013479 if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD
13480 || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013481 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
13482 }
Dianne Hackbornfae76f52009-07-16 13:41:23 -070013483 if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED
13484 && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013485 config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
13486 }
Jack Palevichb90d28c2009-07-22 15:35:24 -070013487 config.reqGlEsVersion = GL_ES_VERSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013488 }
13489 return config;
13490 }
13491
13492 public Configuration getConfiguration() {
13493 Configuration ci;
13494 synchronized(this) {
13495 ci = new Configuration(mConfiguration);
13496 }
13497 return ci;
13498 }
13499
Dianne Hackborn31ca8542011-07-19 14:58:28 -070013500 public void updatePersistentConfiguration(Configuration values) {
13501 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
13502 "updateConfiguration()");
13503 enforceCallingPermission(android.Manifest.permission.WRITE_SETTINGS,
13504 "updateConfiguration()");
13505 if (values == null) {
13506 throw new NullPointerException("Configuration must not be null");
13507 }
13508
13509 synchronized(this) {
13510 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn813075a62011-11-14 17:45:19 -080013511 updateConfigurationLocked(values, null, true, false);
Dianne Hackborn31ca8542011-07-19 14:58:28 -070013512 Binder.restoreCallingIdentity(origId);
13513 }
13514 }
13515
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013516 public void updateConfiguration(Configuration values) {
13517 enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
13518 "updateConfiguration()");
13519
13520 synchronized(this) {
13521 if (values == null && mWindowManager != null) {
13522 // sentinel: fetch the current configuration from the window manager
13523 values = mWindowManager.computeNewConfiguration();
13524 }
Dianne Hackborn7d608422011-08-07 16:24:18 -070013525
13526 if (mWindowManager != null) {
13527 mProcessList.applyDisplaySize(mWindowManager);
13528 }
13529
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013530 final long origId = Binder.clearCallingIdentity();
Dianne Hackborn31ca8542011-07-19 14:58:28 -070013531 if (values != null) {
13532 Settings.System.clearConfiguration(values);
13533 }
Dianne Hackborn813075a62011-11-14 17:45:19 -080013534 updateConfigurationLocked(values, null, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013535 Binder.restoreCallingIdentity(origId);
13536 }
13537 }
13538
13539 /**
13540 * Do either or both things: (1) change the current configuration, and (2)
13541 * make sure the given activity is running with the (now) current
13542 * configuration. Returns true if the activity has been left running, or
13543 * false if <var>starting</var> is being destroyed to match the new
13544 * configuration.
Dianne Hackborn31ca8542011-07-19 14:58:28 -070013545 * @param persistent TODO
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013546 */
13547 public boolean updateConfigurationLocked(Configuration values,
Dianne Hackborn813075a62011-11-14 17:45:19 -080013548 ActivityRecord starting, boolean persistent, boolean initLocale) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013549 int changes = 0;
13550
13551 boolean kept = true;
13552
13553 if (values != null) {
13554 Configuration newConfig = new Configuration(mConfiguration);
13555 changes = newConfig.updateFrom(values);
13556 if (changes != 0) {
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013557 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013558 Slog.i(TAG, "Updating configuration to: " + values);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013559 }
13560
Doug Zongker2bec3d42009-12-04 12:52:44 -080013561 EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013562
Dianne Hackborn813075a62011-11-14 17:45:19 -080013563 if (values.locale != null && !initLocale) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013564 saveLocaleLocked(values.locale,
13565 !values.locale.equals(mConfiguration.locale),
13566 values.userSetLocale);
13567 }
13568
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013569 mConfigurationSeq++;
13570 if (mConfigurationSeq <= 0) {
13571 mConfigurationSeq = 1;
13572 }
13573 newConfig.seq = mConfigurationSeq;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013574 mConfiguration = newConfig;
Joe Onorato8a9b2202010-02-26 18:56:32 -080013575 Slog.i(TAG, "Config changed: " + newConfig);
Dianne Hackborn813075a62011-11-14 17:45:19 -080013576
13577 final Configuration configCopy = new Configuration(mConfiguration);
13578
Dianne Hackborn826d17c2009-11-12 12:55:51 -080013579 AttributeCache ac = AttributeCache.instance();
13580 if (ac != null) {
Dianne Hackborn813075a62011-11-14 17:45:19 -080013581 ac.updateConfiguration(configCopy);
Dianne Hackborn826d17c2009-11-12 12:55:51 -080013582 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013583
Dianne Hackborn2f0b1752011-05-31 17:59:49 -070013584 // Make sure all resources in our process are updated
13585 // right now, so that anyone who is going to retrieve
13586 // resource values after we return will be sure to get
13587 // the new ones. This is especially important during
13588 // boot, where the first config change needs to guarantee
13589 // all resources have that config before following boot
13590 // code is executed.
Dianne Hackborn813075a62011-11-14 17:45:19 -080013591 mSystemThread.applyConfigurationToResources(configCopy);
Dianne Hackborn2f0b1752011-05-31 17:59:49 -070013592
Dianne Hackborn31ca8542011-07-19 14:58:28 -070013593 if (persistent && Settings.System.hasInterestingConfigurationChanges(changes)) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080013594 Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
Dianne Hackborn813075a62011-11-14 17:45:19 -080013595 msg.obj = new Configuration(configCopy);
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080013596 mHandler.sendMessage(msg);
13597 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013598
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013599 for (int i=mLruProcesses.size()-1; i>=0; i--) {
13600 ProcessRecord app = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013601 try {
13602 if (app.thread != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013603 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
Dianne Hackborndc6b6352009-09-30 14:20:09 -070013604 + app.processName + " new config " + mConfiguration);
Dianne Hackborn813075a62011-11-14 17:45:19 -080013605 app.thread.scheduleConfigurationChanged(configCopy);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013606 }
13607 } catch (Exception e) {
13608 }
13609 }
13610 Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -080013611 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
13612 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013613 broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
13614 null, false, false, MY_PID, Process.SYSTEM_UID);
Dianne Hackborn362d5b92009-11-11 18:04:39 -080013615 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
13616 broadcastIntentLocked(null, null,
13617 new Intent(Intent.ACTION_LOCALE_CHANGED),
13618 null, null, 0, null, null,
13619 null, false, false, MY_PID, Process.SYSTEM_UID);
13620 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013621 }
13622 }
13623
13624 if (changes != 0 && starting == null) {
13625 // If the configuration changed, and the caller is not already
13626 // in the process of starting an activity, then find the top
13627 // activity to check if its configuration needs to change.
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013628 starting = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013629 }
13630
13631 if (starting != null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070013632 kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
Dianne Hackborn5f4d6432010-12-21 20:40:11 -080013633 // And we need to make sure at this point that all other activities
13634 // are made visible with the correct configuration.
13635 mMainStack.ensureActivitiesVisibleLocked(starting, changes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013636 }
13637
Dianne Hackborne36d6e22010-02-17 19:46:25 -080013638 if (values != null && mWindowManager != null) {
13639 mWindowManager.setNewConfiguration(mConfiguration);
13640 }
13641
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013642 return kept;
13643 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013644
13645 /**
13646 * Save the locale. You must be inside a synchronized (this) block.
13647 */
13648 private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
13649 if(isDiff) {
13650 SystemProperties.set("user.language", l.getLanguage());
13651 SystemProperties.set("user.region", l.getCountry());
13652 }
13653
13654 if(isPersist) {
13655 SystemProperties.set("persist.sys.language", l.getLanguage());
13656 SystemProperties.set("persist.sys.country", l.getCountry());
13657 SystemProperties.set("persist.sys.localevar", l.getVariant());
13658 }
13659 }
13660
13661 // =========================================================
13662 // LIFETIME MANAGEMENT
13663 // =========================================================
13664
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013665 private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
Dianne Hackborne02c88a2011-10-28 13:58:15 -070013666 ProcessRecord TOP_APP, boolean recursed, boolean doingAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013667 if (mAdjSeq == app.adjSeq) {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013668 // This adjustment has already been computed. If we are calling
13669 // from the top, we may have already computed our adjustment with
13670 // an earlier hidden adjustment that isn't really for us... if
13671 // so, use the new hidden adjustment.
13672 if (!recursed && app.hidden) {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013673 app.curAdj = app.curRawAdj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013674 }
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013675 return app.curRawAdj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013676 }
13677
13678 if (app.thread == null) {
13679 app.adjSeq = mAdjSeq;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013680 app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborne02c88a2011-10-28 13:58:15 -070013681 return (app.curAdj=ProcessList.HIDDEN_APP_MAX_ADJ);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013682 }
13683
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013684 app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
13685 app.adjSource = null;
13686 app.adjTarget = null;
13687 app.empty = false;
13688 app.hidden = false;
13689
13690 final int activitiesSize = app.activities.size();
13691
Dianne Hackborn7d608422011-08-07 16:24:18 -070013692 if (app.maxAdj <= ProcessList.FOREGROUND_APP_ADJ) {
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013693 // The max adjustment doesn't allow this app to be anything
13694 // below foreground, so it is not worth doing work for it.
13695 app.adjType = "fixed";
13696 app.adjSeq = mAdjSeq;
13697 app.curRawAdj = app.maxAdj;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013698 app.foregroundActivities = false;
Dianne Hackborn287952c2010-09-22 22:34:31 -070013699 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013700 app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013701 // System process can do UI, and when they do we want to have
13702 // them trim their memory after the user leaves the UI. To
13703 // facilitate this, here we need to determine whether or not it
13704 // is currently showing UI.
13705 app.systemNoUi = true;
13706 if (app == TOP_APP) {
13707 app.systemNoUi = false;
13708 } else if (activitiesSize > 0) {
13709 for (int j = 0; j < activitiesSize; j++) {
13710 final ActivityRecord r = app.activities.get(j);
13711 if (r.visible) {
13712 app.systemNoUi = false;
13713 break;
13714 }
13715 }
13716 }
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013717 return (app.curAdj=app.maxAdj);
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013718 }
13719
13720 final boolean hadForegroundActivities = app.foregroundActivities;
13721
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013722 app.foregroundActivities = false;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013723 app.keeping = false;
13724 app.systemNoUi = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013725
The Android Open Source Project4df24232009-03-05 14:34:35 -080013726 // Determine the importance of the process, starting with most
13727 // important to least, and assign an appropriate OOM adjustment.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013728 int adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013729 int schedGroup;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013730 if (app == TOP_APP) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013731 // The last app on the list is the foreground app.
Dianne Hackborn7d608422011-08-07 16:24:18 -070013732 adj = ProcessList.FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013733 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013734 app.adjType = "top-activity";
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013735 app.foregroundActivities = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013736 } else if (app.instrumentationClass != null) {
13737 // Don't want to kill running instrumentation.
Dianne Hackborn7d608422011-08-07 16:24:18 -070013738 adj = ProcessList.FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013739 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013740 app.adjType = "instrumentation";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013741 } else if (app.curReceiver != null ||
13742 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
13743 // An app that is currently receiving a broadcast also
13744 // counts as being in the foreground.
Dianne Hackborn7d608422011-08-07 16:24:18 -070013745 adj = ProcessList.FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013746 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013747 app.adjType = "broadcast";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013748 } else if (app.executingServices.size() > 0) {
13749 // An app that is currently executing a service callback also
13750 // counts as being in the foreground.
Dianne Hackborn7d608422011-08-07 16:24:18 -070013751 adj = ProcessList.FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013752 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013753 app.adjType = "exec-service";
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013754 } else if (activitiesSize > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013755 // This app is in the background with paused activities.
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013756 // We inspect activities to potentially upgrade adjustment further below.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013757 adj = hiddenAdj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013758 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013759 app.hidden = true;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070013760 app.adjType = "bg-activities";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013761 } else {
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013762 // A very not-needed process. If this is lower in the lru list,
13763 // we will push it in to the empty bucket.
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013764 adj = hiddenAdj;
13765 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013766 app.hidden = true;
13767 app.empty = true;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013768 app.adjType = "bg-empty";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013769 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013770
13771 // Examine all activities if not already foreground.
13772 if (!app.foregroundActivities && activitiesSize > 0) {
13773 for (int j = 0; j < activitiesSize; j++) {
13774 final ActivityRecord r = app.activities.get(j);
13775 if (r.visible) {
13776 // App has a visible activity; only upgrade adjustment.
Dianne Hackborn7d608422011-08-07 16:24:18 -070013777 if (adj > ProcessList.VISIBLE_APP_ADJ) {
13778 adj = ProcessList.VISIBLE_APP_ADJ;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013779 app.adjType = "visible";
13780 }
13781 schedGroup = Process.THREAD_GROUP_DEFAULT;
13782 app.hidden = false;
13783 app.foregroundActivities = true;
13784 break;
13785 } else if (r.state == ActivityState.PAUSING || r.state == ActivityState.PAUSED
13786 || r.state == ActivityState.STOPPING) {
13787 // Only upgrade adjustment.
Dianne Hackborn7d608422011-08-07 16:24:18 -070013788 if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
13789 adj = ProcessList.PERCEPTIBLE_APP_ADJ;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013790 app.adjType = "stopping";
13791 }
Dianne Hackborn8bf0aa92011-11-29 13:54:43 -080013792 app.hidden = false;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013793 app.foregroundActivities = true;
13794 }
13795 }
13796 }
13797
Dianne Hackborn7d608422011-08-07 16:24:18 -070013798 if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn83a6f452011-01-27 17:17:19 -080013799 if (app.foregroundServices) {
13800 // The user is aware of this app, so make it visible.
Dianne Hackborn7d608422011-08-07 16:24:18 -070013801 adj = ProcessList.PERCEPTIBLE_APP_ADJ;
Dianne Hackborn98cfebc2011-10-18 13:17:33 -070013802 app.hidden = false;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080013803 app.adjType = "foreground-service";
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013804 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080013805 } else if (app.forcingToForeground != null) {
13806 // The user is aware of this app, so make it visible.
Dianne Hackborn7d608422011-08-07 16:24:18 -070013807 adj = ProcessList.PERCEPTIBLE_APP_ADJ;
Dianne Hackborn98cfebc2011-10-18 13:17:33 -070013808 app.hidden = false;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080013809 app.adjType = "force-foreground";
13810 app.adjSource = app.forcingToForeground;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013811 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080013812 }
13813 }
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070013814
Dianne Hackborn7d608422011-08-07 16:24:18 -070013815 if (adj > ProcessList.HEAVY_WEIGHT_APP_ADJ && app == mHeavyWeightProcess) {
Dianne Hackborn83a6f452011-01-27 17:17:19 -080013816 // We don't want to kill the current heavy-weight process.
Dianne Hackborn7d608422011-08-07 16:24:18 -070013817 adj = ProcessList.HEAVY_WEIGHT_APP_ADJ;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080013818 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborn98cfebc2011-10-18 13:17:33 -070013819 app.hidden = false;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080013820 app.adjType = "heavy";
13821 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013822
Dianne Hackborn7d608422011-08-07 16:24:18 -070013823 if (adj > ProcessList.HOME_APP_ADJ && app == mHomeProcess) {
Dianne Hackborn83a6f452011-01-27 17:17:19 -080013824 // This process is hosting what we currently consider to be the
13825 // home app, so we don't want to let it go into the background.
Dianne Hackborn7d608422011-08-07 16:24:18 -070013826 adj = ProcessList.HOME_APP_ADJ;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080013827 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
Dianne Hackborn98cfebc2011-10-18 13:17:33 -070013828 app.hidden = false;
Dianne Hackborn83a6f452011-01-27 17:17:19 -080013829 app.adjType = "home";
13830 }
Dianne Hackborn98cfebc2011-10-18 13:17:33 -070013831
Dianne Hackbornf35fe232011-11-01 19:25:20 -070013832 if (adj > ProcessList.PREVIOUS_APP_ADJ && app == mPreviousProcess
13833 && app.activities.size() > 0) {
13834 // This was the previous process that showed UI to the user.
13835 // We want to try to keep it around more aggressively, to give
13836 // a good experience around switching between two apps.
13837 adj = ProcessList.PREVIOUS_APP_ADJ;
13838 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
13839 app.hidden = false;
13840 app.adjType = "previous";
13841 }
13842
Dianne Hackborn98cfebc2011-10-18 13:17:33 -070013843 if (false) Slog.i(TAG, "OOM " + app + ": initial adj=" + adj
13844 + " reason=" + app.adjType);
13845
The Android Open Source Project4df24232009-03-05 14:34:35 -080013846 // By default, we use the computed adjustment. It may be changed if
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013847 // there are applications dependent on our services or providers, but
13848 // this gives us a baseline and makes sure we don't get into an
13849 // infinite recursion.
13850 app.adjSeq = mAdjSeq;
13851 app.curRawAdj = adj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013852
Christopher Tate6fa95972009-06-05 18:43:55 -070013853 if (mBackupTarget != null && app == mBackupTarget.app) {
13854 // If possible we want to avoid killing apps while they're being backed up
Dianne Hackborn7d608422011-08-07 16:24:18 -070013855 if (adj > ProcessList.BACKUP_APP_ADJ) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080013856 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);
Dianne Hackborn7d608422011-08-07 16:24:18 -070013857 adj = ProcessList.BACKUP_APP_ADJ;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070013858 app.adjType = "backup";
Dianne Hackborndd71fc82009-12-16 19:24:32 -080013859 app.hidden = false;
Christopher Tate6fa95972009-06-05 18:43:55 -070013860 }
13861 }
13862
Dianne Hackborn7d608422011-08-07 16:24:18 -070013863 if (app.services.size() != 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013864 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013865 final long now = SystemClock.uptimeMillis();
13866 // This process is more important if the top activity is
13867 // bound to the service.
Dianne Hackborn860755f2010-06-03 18:47:52 -070013868 Iterator<ServiceRecord> jt = app.services.iterator();
Dianne Hackborn7d608422011-08-07 16:24:18 -070013869 while (jt.hasNext() && adj > ProcessList.FOREGROUND_APP_ADJ) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070013870 ServiceRecord s = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013871 if (s.startRequested) {
Dianne Hackborn98cfebc2011-10-18 13:17:33 -070013872 if (app.hasShownUi && app != mHomeProcess) {
Dianne Hackbornf0754f5b2011-07-21 16:02:07 -070013873 // If this process has shown some UI, let it immediately
13874 // go to the LRU list because it may be pretty heavy with
13875 // UI stuff. We'll tag it with a label just to help
13876 // debug and understand what is going on.
Dianne Hackborne02c88a2011-10-28 13:58:15 -070013877 if (adj > ProcessList.SERVICE_ADJ) {
Dianne Hackbornf0754f5b2011-07-21 16:02:07 -070013878 app.adjType = "started-bg-ui-services";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013879 }
Dianne Hackbornf0754f5b2011-07-21 16:02:07 -070013880 } else {
13881 if (now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
13882 // This service has seen some activity within
13883 // recent memory, so we will keep its process ahead
13884 // of the background processes.
Dianne Hackborne02c88a2011-10-28 13:58:15 -070013885 if (adj > ProcessList.SERVICE_ADJ) {
13886 adj = ProcessList.SERVICE_ADJ;
Dianne Hackbornf0754f5b2011-07-21 16:02:07 -070013887 app.adjType = "started-services";
13888 app.hidden = false;
13889 }
13890 }
13891 // If we have let the service slide into the background
13892 // state, still have some text describing what it is doing
13893 // even though the service no longer has an impact.
Dianne Hackborne02c88a2011-10-28 13:58:15 -070013894 if (adj > ProcessList.SERVICE_ADJ) {
Dianne Hackbornf0754f5b2011-07-21 16:02:07 -070013895 app.adjType = "started-bg-services";
13896 }
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080013897 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070013898 // Don't kill this process because it is doing work; it
13899 // has said it is doing work.
13900 app.keeping = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013901 }
Dianne Hackborn7d608422011-08-07 16:24:18 -070013902 if (s.connections.size() > 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
Dianne Hackborn09c916b2009-12-08 14:50:51 -080013903 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070013904 Iterator<ArrayList<ConnectionRecord>> kt
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013905 = s.connections.values().iterator();
Dianne Hackborn7d608422011-08-07 16:24:18 -070013906 while (kt.hasNext() && adj > ProcessList.FOREGROUND_APP_ADJ) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070013907 ArrayList<ConnectionRecord> clist = kt.next();
Dianne Hackborn7d608422011-08-07 16:24:18 -070013908 for (int i=0; i<clist.size() && adj > ProcessList.FOREGROUND_APP_ADJ; i++) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070013909 // XXX should compute this based on the max of
13910 // all connected clients.
13911 ConnectionRecord cr = clist.get(i);
13912 if (cr.binding.client == app) {
13913 // Binding to ourself is not interesting.
13914 continue;
13915 }
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013916 if ((cr.flags&Context.BIND_WAIVE_PRIORITY) == 0) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070013917 ProcessRecord client = cr.binding.client;
Dianne Hackborn130b0d22011-07-26 22:07:48 -070013918 int clientAdj = adj;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070013919 int myHiddenAdj = hiddenAdj;
13920 if (myHiddenAdj > client.hiddenAdj) {
Dianne Hackborn7d608422011-08-07 16:24:18 -070013921 if (client.hiddenAdj >= ProcessList.VISIBLE_APP_ADJ) {
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070013922 myHiddenAdj = client.hiddenAdj;
13923 } else {
Dianne Hackborn7d608422011-08-07 16:24:18 -070013924 myHiddenAdj = ProcessList.VISIBLE_APP_ADJ;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070013925 }
13926 }
Dianne Hackborn130b0d22011-07-26 22:07:48 -070013927 clientAdj = computeOomAdjLocked(
Dianne Hackborne02c88a2011-10-28 13:58:15 -070013928 client, myHiddenAdj, TOP_APP, true, doingAll);
Dianne Hackborn130b0d22011-07-26 22:07:48 -070013929 String adjType = null;
13930 if ((cr.flags&Context.BIND_ALLOW_OOM_MANAGEMENT) != 0) {
13931 // Not doing bind OOM management, so treat
13932 // this guy more like a started service.
Dianne Hackborn98cfebc2011-10-18 13:17:33 -070013933 if (app.hasShownUi && app != mHomeProcess) {
Dianne Hackborn130b0d22011-07-26 22:07:48 -070013934 // If this process has shown some UI, let it immediately
13935 // go to the LRU list because it may be pretty heavy with
13936 // UI stuff. We'll tag it with a label just to help
13937 // debug and understand what is going on.
13938 if (adj > clientAdj) {
13939 adjType = "bound-bg-ui-services";
13940 }
Dianne Hackborn98cfebc2011-10-18 13:17:33 -070013941 app.hidden = false;
Dianne Hackborn130b0d22011-07-26 22:07:48 -070013942 clientAdj = adj;
13943 } else {
13944 if (now >= (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
13945 // This service has not seen activity within
13946 // recent memory, so allow it to drop to the
13947 // LRU list if there is no other reason to keep
13948 // it around. We'll also tag it with a label just
13949 // to help debug and undertand what is going on.
13950 if (adj > clientAdj) {
13951 adjType = "bound-bg-services";
13952 }
13953 clientAdj = adj;
13954 }
13955 }
13956 }
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070013957 if (adj > clientAdj) {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013958 // If this process has recently shown UI, and
13959 // the process that is binding to it is less
13960 // important than being visible, then we don't
13961 // care about the binding as much as we care
13962 // about letting this process get into the LRU
13963 // list to be killed and restarted if needed for
13964 // memory.
Dianne Hackborn98cfebc2011-10-18 13:17:33 -070013965 if (app.hasShownUi && app != mHomeProcess
13966 && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013967 adjType = "bound-bg-ui-services";
13968 } else {
13969 if ((cr.flags&(Context.BIND_ABOVE_CLIENT
13970 |Context.BIND_IMPORTANT)) != 0) {
13971 adj = clientAdj;
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -070013972 } else if ((cr.flags&Context.BIND_NOT_VISIBLE) != 0
13973 && clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ
13974 && adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
13975 adj = ProcessList.PERCEPTIBLE_APP_ADJ;
13976 } else if (clientAdj > ProcessList.VISIBLE_APP_ADJ) {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013977 adj = clientAdj;
13978 } else {
Dianne Hackborn2c84cfc2011-10-31 15:39:59 -070013979 app.pendingUiClean = true;
13980 if (adj > ProcessList.VISIBLE_APP_ADJ) {
13981 adj = ProcessList.VISIBLE_APP_ADJ;
13982 }
Dianne Hackbornc68c9132011-07-29 01:25:18 -070013983 }
13984 if (!client.hidden) {
13985 app.hidden = false;
13986 }
13987 if (client.keeping) {
13988 app.keeping = true;
13989 }
13990 adjType = "service";
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070013991 }
Dianne Hackborn130b0d22011-07-26 22:07:48 -070013992 }
13993 if (adjType != null) {
13994 app.adjType = adjType;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070013995 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
13996 .REASON_SERVICE_IN_USE;
13997 app.adjSource = cr.binding.client;
Dianne Hackborn905577f2011-09-07 18:31:28 -070013998 app.adjSourceOom = clientAdj;
Dianne Hackborn43d9ac82010-08-25 15:06:25 -070013999 app.adjTarget = s.name;
14000 }
14001 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
14002 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
14003 schedGroup = Process.THREAD_GROUP_DEFAULT;
14004 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014005 }
14006 }
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014007 if ((cr.flags&Context.BIND_ADJUST_WITH_ACTIVITY) != 0) {
14008 ActivityRecord a = cr.activity;
Dianne Hackborn7d608422011-08-07 16:24:18 -070014009 if (a != null && adj > ProcessList.FOREGROUND_APP_ADJ &&
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014010 (a.visible || a.state == ActivityState.RESUMED
14011 || a.state == ActivityState.PAUSING)) {
Dianne Hackborn7d608422011-08-07 16:24:18 -070014012 adj = ProcessList.FOREGROUND_APP_ADJ;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014013 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
14014 schedGroup = Process.THREAD_GROUP_DEFAULT;
14015 }
14016 app.hidden = false;
14017 app.adjType = "service";
14018 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
14019 .REASON_SERVICE_IN_USE;
14020 app.adjSource = a;
Dianne Hackborn905577f2011-09-07 18:31:28 -070014021 app.adjSourceOom = adj;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014022 app.adjTarget = s.name;
14023 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014024 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014025 }
14026 }
14027 }
14028 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070014029
Dianne Hackborn287952c2010-09-22 22:34:31 -070014030 // Finally, if this process has active services running in it, we
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070014031 // would like to avoid killing it unless it would prevent the current
14032 // application from running. By default we put the process in
14033 // with the rest of the background processes; as we scan through
14034 // its services we may bump it up from there.
14035 if (adj > hiddenAdj) {
14036 adj = hiddenAdj;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014037 app.hidden = false;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070014038 app.adjType = "bg-services";
14039 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014040 }
14041
Dianne Hackborn7d608422011-08-07 16:24:18 -070014042 if (app.pubProviders.size() != 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014043 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070014044 Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
Dianne Hackborn7d608422011-08-07 16:24:18 -070014045 while (jt.hasNext() && (adj > ProcessList.FOREGROUND_APP_ADJ
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014046 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Dianne Hackborn860755f2010-06-03 18:47:52 -070014047 ContentProviderRecord cpr = jt.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014048 if (cpr.clients.size() != 0) {
14049 Iterator<ProcessRecord> kt = cpr.clients.iterator();
Dianne Hackborn7d608422011-08-07 16:24:18 -070014050 while (kt.hasNext() && adj > ProcessList.FOREGROUND_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014051 ProcessRecord client = kt.next();
The Android Open Source Project10592532009-03-18 17:39:46 -070014052 if (client == app) {
14053 // Being our own client is not interesting.
14054 continue;
14055 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014056 int myHiddenAdj = hiddenAdj;
14057 if (myHiddenAdj > client.hiddenAdj) {
Dianne Hackborn7d608422011-08-07 16:24:18 -070014058 if (client.hiddenAdj > ProcessList.FOREGROUND_APP_ADJ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014059 myHiddenAdj = client.hiddenAdj;
14060 } else {
Dianne Hackborn7d608422011-08-07 16:24:18 -070014061 myHiddenAdj = ProcessList.FOREGROUND_APP_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014062 }
14063 }
14064 int clientAdj = computeOomAdjLocked(
Dianne Hackborne02c88a2011-10-28 13:58:15 -070014065 client, myHiddenAdj, TOP_APP, true, doingAll);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014066 if (adj > clientAdj) {
Dianne Hackborn98cfebc2011-10-18 13:17:33 -070014067 if (app.hasShownUi && app != mHomeProcess
14068 && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014069 app.adjType = "bg-ui-provider";
14070 } else {
Dianne Hackborn7d608422011-08-07 16:24:18 -070014071 adj = clientAdj > ProcessList.FOREGROUND_APP_ADJ
14072 ? clientAdj : ProcessList.FOREGROUND_APP_ADJ;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014073 app.adjType = "provider";
14074 }
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014075 if (!client.hidden) {
14076 app.hidden = false;
14077 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070014078 if (client.keeping) {
14079 app.keeping = true;
14080 }
Dianne Hackborndd9b82c2009-09-03 00:18:47 -070014081 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
14082 .REASON_PROVIDER_IN_USE;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014083 app.adjSource = client;
Dianne Hackborn905577f2011-09-07 18:31:28 -070014084 app.adjSourceOom = clientAdj;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070014085 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014086 }
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014087 if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
14088 schedGroup = Process.THREAD_GROUP_DEFAULT;
14089 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014090 }
14091 }
14092 // If the provider has external (non-framework) process
14093 // dependencies, ensure that its adjustment is at least
14094 // FOREGROUND_APP_ADJ.
14095 if (cpr.externals != 0) {
Dianne Hackborn7d608422011-08-07 16:24:18 -070014096 if (adj > ProcessList.FOREGROUND_APP_ADJ) {
14097 adj = ProcessList.FOREGROUND_APP_ADJ;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014098 schedGroup = Process.THREAD_GROUP_DEFAULT;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014099 app.hidden = false;
Dianne Hackborn287952c2010-09-22 22:34:31 -070014100 app.keeping = true;
Dianne Hackbornde42bb62009-08-05 12:26:15 -070014101 app.adjType = "provider";
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070014102 app.adjTarget = cpr.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014103 }
14104 }
14105 }
14106 }
14107
14108 app.curRawAdj = adj;
14109
Joe Onorato8a9b2202010-02-26 18:56:32 -080014110 //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014111 // " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
14112 if (adj > app.maxAdj) {
14113 adj = app.maxAdj;
Dianne Hackborn7d608422011-08-07 16:24:18 -070014114 if (app.maxAdj <= ProcessList.PERCEPTIBLE_APP_ADJ) {
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014115 schedGroup = Process.THREAD_GROUP_DEFAULT;
14116 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014117 }
Dianne Hackborn7d608422011-08-07 16:24:18 -070014118 if (adj < ProcessList.HIDDEN_APP_MIN_ADJ) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070014119 app.keeping = true;
14120 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014121
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014122 if (app.hasAboveClient) {
14123 // If this process has bound to any services with BIND_ABOVE_CLIENT,
14124 // then we need to drop its adjustment to be lower than the service's
14125 // in order to honor the request. We want to drop it by one adjustment
14126 // level... but there is special meaning applied to various levels so
14127 // we will skip some of them.
Dianne Hackborn7d608422011-08-07 16:24:18 -070014128 if (adj < ProcessList.FOREGROUND_APP_ADJ) {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014129 // System process will not get dropped, ever
Dianne Hackborn7d608422011-08-07 16:24:18 -070014130 } else if (adj < ProcessList.VISIBLE_APP_ADJ) {
14131 adj = ProcessList.VISIBLE_APP_ADJ;
14132 } else if (adj < ProcessList.PERCEPTIBLE_APP_ADJ) {
14133 adj = ProcessList.PERCEPTIBLE_APP_ADJ;
14134 } else if (adj < ProcessList.HIDDEN_APP_MIN_ADJ) {
14135 adj = ProcessList.HIDDEN_APP_MIN_ADJ;
Dianne Hackborne02c88a2011-10-28 13:58:15 -070014136 } else if (adj < ProcessList.HIDDEN_APP_MAX_ADJ) {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014137 adj++;
14138 }
14139 }
14140
Dianne Hackborne02c88a2011-10-28 13:58:15 -070014141 if (adj == ProcessList.SERVICE_ADJ) {
14142 if (doingAll) {
14143 app.serviceb = mNewNumServiceProcs > (mNumServiceProcs/3);
14144 mNewNumServiceProcs++;
14145 }
14146 if (app.serviceb) {
14147 adj = ProcessList.SERVICE_B_ADJ;
14148 }
14149 } else {
14150 app.serviceb = false;
14151 }
14152
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014153 app.curAdj = adj;
Dianne Hackborn09c916b2009-12-08 14:50:51 -080014154 app.curSchedGroup = schedGroup;
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070014155
14156 if (hadForegroundActivities != app.foregroundActivities) {
Jeff Sharkey287bd832011-05-28 19:36:26 -070014157 mHandler.obtainMessage(DISPATCH_FOREGROUND_ACTIVITIES_CHANGED, app.pid, app.info.uid,
14158 app.foregroundActivities).sendToTarget();
Jeff Sharkeyd5cdd592011-05-03 20:27:17 -070014159 }
14160
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014161 return app.curRawAdj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014162 }
14163
14164 /**
14165 * Ask a given process to GC right now.
14166 */
14167 final void performAppGcLocked(ProcessRecord app) {
14168 try {
14169 app.lastRequestedGc = SystemClock.uptimeMillis();
14170 if (app.thread != null) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014171 if (app.reportLowMemory) {
14172 app.reportLowMemory = false;
14173 app.thread.scheduleLowMemory();
14174 } else {
14175 app.thread.processInBackground();
14176 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014177 }
14178 } catch (Exception e) {
14179 // whatever.
14180 }
14181 }
14182
14183 /**
14184 * Returns true if things are idle enough to perform GCs.
14185 */
Josh Bartel7f208742010-02-25 11:01:44 -060014186 private final boolean canGcNowLocked() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014187 return mParallelBroadcasts.size() == 0
14188 && mOrderedBroadcasts.size() == 0
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070014189 && (mSleeping || (mMainStack.mResumedActivity != null &&
14190 mMainStack.mResumedActivity.idle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014191 }
14192
14193 /**
14194 * Perform GCs on all processes that are waiting for it, but only
14195 * if things are idle.
14196 */
14197 final void performAppGcsLocked() {
14198 final int N = mProcessesToGc.size();
14199 if (N <= 0) {
14200 return;
14201 }
Josh Bartel7f208742010-02-25 11:01:44 -060014202 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014203 while (mProcessesToGc.size() > 0) {
14204 ProcessRecord proc = mProcessesToGc.remove(0);
Dianne Hackborn7d608422011-08-07 16:24:18 -070014205 if (proc.curRawAdj > ProcessList.PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014206 if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
14207 <= SystemClock.uptimeMillis()) {
14208 // To avoid spamming the system, we will GC processes one
14209 // at a time, waiting a few seconds between each.
14210 performAppGcLocked(proc);
14211 scheduleAppGcsLocked();
14212 return;
14213 } else {
14214 // It hasn't been long enough since we last GCed this
14215 // process... put it in the list to wait for its time.
14216 addProcessToGcListLocked(proc);
14217 break;
14218 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014219 }
14220 }
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014221
14222 scheduleAppGcsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014223 }
14224 }
14225
14226 /**
14227 * If all looks good, perform GCs on all processes waiting for them.
14228 */
14229 final void performAppGcsIfAppropriateLocked() {
Josh Bartel7f208742010-02-25 11:01:44 -060014230 if (canGcNowLocked()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014231 performAppGcsLocked();
14232 return;
14233 }
14234 // Still not idle, wait some more.
14235 scheduleAppGcsLocked();
14236 }
14237
14238 /**
14239 * Schedule the execution of all pending app GCs.
14240 */
14241 final void scheduleAppGcsLocked() {
14242 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014243
14244 if (mProcessesToGc.size() > 0) {
14245 // Schedule a GC for the time to the next process.
14246 ProcessRecord proc = mProcessesToGc.get(0);
14247 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
14248
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014249 long when = proc.lastRequestedGc + GC_MIN_INTERVAL;
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014250 long now = SystemClock.uptimeMillis();
14251 if (when < (now+GC_TIMEOUT)) {
14252 when = now + GC_TIMEOUT;
14253 }
14254 mHandler.sendMessageAtTime(msg, when);
14255 }
14256 }
14257
14258 /**
14259 * Add a process to the array of processes waiting to be GCed. Keeps the
14260 * list in sorted order by the last GC time. The process can't already be
14261 * on the list.
14262 */
14263 final void addProcessToGcListLocked(ProcessRecord proc) {
14264 boolean added = false;
14265 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
14266 if (mProcessesToGc.get(i).lastRequestedGc <
14267 proc.lastRequestedGc) {
14268 added = true;
14269 mProcessesToGc.add(i+1, proc);
14270 break;
14271 }
14272 }
14273 if (!added) {
14274 mProcessesToGc.add(0, proc);
14275 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014276 }
14277
14278 /**
14279 * Set up to ask a process to GC itself. This will either do it
14280 * immediately, or put it on the list of processes to gc the next
14281 * time things are idle.
14282 */
14283 final void scheduleAppGcLocked(ProcessRecord app) {
14284 long now = SystemClock.uptimeMillis();
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014285 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014286 return;
14287 }
14288 if (!mProcessesToGc.contains(app)) {
Dianne Hackbornfd12af42009-08-27 00:44:33 -070014289 addProcessToGcListLocked(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014290 scheduleAppGcsLocked();
14291 }
14292 }
14293
Dianne Hackborn287952c2010-09-22 22:34:31 -070014294 final void checkExcessivePowerUsageLocked(boolean doKills) {
14295 updateCpuStatsNow();
14296
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070014297 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
Dianne Hackborn287952c2010-09-22 22:34:31 -070014298 boolean doWakeKills = doKills;
14299 boolean doCpuKills = doKills;
14300 if (mLastPowerCheckRealtime == 0) {
14301 doWakeKills = false;
14302 }
14303 if (mLastPowerCheckUptime == 0) {
14304 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070014305 }
14306 if (stats.isScreenOn()) {
Dianne Hackborn287952c2010-09-22 22:34:31 -070014307 doWakeKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070014308 }
14309 final long curRealtime = SystemClock.elapsedRealtime();
Dianne Hackborn287952c2010-09-22 22:34:31 -070014310 final long realtimeSince = curRealtime - mLastPowerCheckRealtime;
14311 final long curUptime = SystemClock.uptimeMillis();
14312 final long uptimeSince = curUptime - mLastPowerCheckUptime;
14313 mLastPowerCheckRealtime = curRealtime;
14314 mLastPowerCheckUptime = curUptime;
14315 if (realtimeSince < WAKE_LOCK_MIN_CHECK_DURATION) {
14316 doWakeKills = false;
14317 }
14318 if (uptimeSince < CPU_MIN_CHECK_DURATION) {
14319 doCpuKills = false;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070014320 }
14321 int i = mLruProcesses.size();
14322 while (i > 0) {
14323 i--;
14324 ProcessRecord app = mLruProcesses.get(i);
Dianne Hackborn287952c2010-09-22 22:34:31 -070014325 if (!app.keeping) {
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070014326 long wtime;
14327 synchronized (stats) {
14328 wtime = stats.getProcessWakeTime(app.info.uid,
14329 app.pid, curRealtime);
14330 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070014331 long wtimeUsed = wtime - app.lastWakeTime;
14332 long cputimeUsed = app.curCpuTime - app.lastCpuTime;
14333 if (DEBUG_POWER) {
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070014334 StringBuilder sb = new StringBuilder(128);
14335 sb.append("Wake for ");
14336 app.toShortString(sb);
14337 sb.append(": over ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070014338 TimeUtils.formatDuration(realtimeSince, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070014339 sb.append(" used ");
Dianne Hackborn287952c2010-09-22 22:34:31 -070014340 TimeUtils.formatDuration(wtimeUsed, sb);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070014341 sb.append(" (");
Dianne Hackborn287952c2010-09-22 22:34:31 -070014342 sb.append((wtimeUsed*100)/realtimeSince);
14343 sb.append("%)");
14344 Slog.i(TAG, sb.toString());
14345 sb.setLength(0);
14346 sb.append("CPU for ");
14347 app.toShortString(sb);
14348 sb.append(": over ");
14349 TimeUtils.formatDuration(uptimeSince, sb);
14350 sb.append(" used ");
14351 TimeUtils.formatDuration(cputimeUsed, sb);
14352 sb.append(" (");
14353 sb.append((cputimeUsed*100)/uptimeSince);
Dianne Hackborn1ebccf52010-08-15 13:04:34 -070014354 sb.append("%)");
14355 Slog.i(TAG, sb.toString());
14356 }
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070014357 // If a process has held a wake lock for more
14358 // than 50% of the time during this period,
14359 // that sounds pad. Kill!
Dianne Hackborn287952c2010-09-22 22:34:31 -070014360 if (doWakeKills && realtimeSince > 0
14361 && ((wtimeUsed*100)/realtimeSince) >= 50) {
14362 synchronized (stats) {
14363 stats.reportExcessiveWakeLocked(app.info.uid, app.processName,
14364 realtimeSince, wtimeUsed);
14365 }
14366 Slog.w(TAG, "Excessive wake lock in " + app.processName
14367 + " (pid " + app.pid + "): held " + wtimeUsed
14368 + " during " + realtimeSince);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070014369 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
14370 app.processName, app.setAdj, "excessive wake lock");
14371 Process.killProcessQuiet(app.pid);
Dianne Hackborn287952c2010-09-22 22:34:31 -070014372 } else if (doCpuKills && uptimeSince > 0
14373 && ((cputimeUsed*100)/uptimeSince) >= 50) {
14374 synchronized (stats) {
14375 stats.reportExcessiveCpuLocked(app.info.uid, app.processName,
14376 uptimeSince, cputimeUsed);
14377 }
14378 Slog.w(TAG, "Excessive CPU in " + app.processName
14379 + " (pid " + app.pid + "): used " + cputimeUsed
14380 + " during " + uptimeSince);
14381 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
14382 app.processName, app.setAdj, "excessive cpu");
14383 Process.killProcessQuiet(app.pid);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070014384 } else {
14385 app.lastWakeTime = wtime;
Dianne Hackborn287952c2010-09-22 22:34:31 -070014386 app.lastCpuTime = app.curCpuTime;
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070014387 }
14388 }
14389 }
14390 }
14391
Dianne Hackborn295e3c22011-08-25 13:19:08 -070014392 private final boolean updateOomAdjLocked(
Dianne Hackborne02c88a2011-10-28 13:58:15 -070014393 ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP, boolean doingAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014394 app.hiddenAdj = hiddenAdj;
14395
14396 if (app.thread == null) {
Dianne Hackborn295e3c22011-08-25 13:19:08 -070014397 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014398 }
14399
Dianne Hackborn287952c2010-09-22 22:34:31 -070014400 final boolean wasKeeping = app.keeping;
14401
Dianne Hackborn295e3c22011-08-25 13:19:08 -070014402 boolean success = true;
14403
Dianne Hackborne02c88a2011-10-28 13:58:15 -070014404 computeOomAdjLocked(app, hiddenAdj, TOP_APP, false, doingAll);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014405
Jeff Brown10e89712011-07-08 18:52:57 -070014406 if (app.curRawAdj != app.setRawAdj) {
Dianne Hackborn905577f2011-09-07 18:31:28 -070014407 if (false) {
14408 // Removing for now. Forcing GCs is not so useful anymore
14409 // with Dalvik, and the new memory level hint facility is
14410 // better for what we need to do these days.
14411 if (app.curRawAdj > ProcessList.FOREGROUND_APP_ADJ
14412 && app.setRawAdj <= ProcessList.FOREGROUND_APP_ADJ) {
14413 // If this app is transitioning from foreground to
14414 // non-foreground, have it do a gc.
14415 scheduleAppGcLocked(app);
14416 } else if (app.curRawAdj >= ProcessList.HIDDEN_APP_MIN_ADJ
14417 && app.setRawAdj < ProcessList.HIDDEN_APP_MIN_ADJ) {
14418 // Likewise do a gc when an app is moving in to the
14419 // background (such as a service stopping).
14420 scheduleAppGcLocked(app);
14421 }
Jeff Brown10e89712011-07-08 18:52:57 -070014422 }
Dianne Hackborn287952c2010-09-22 22:34:31 -070014423
Jeff Brown10e89712011-07-08 18:52:57 -070014424 if (wasKeeping && !app.keeping) {
14425 // This app is no longer something we want to keep. Note
14426 // its current wake lock time to later know to kill it if
14427 // it is not behaving well.
14428 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
14429 synchronized (stats) {
14430 app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
14431 app.pid, SystemClock.elapsedRealtime());
14432 }
14433 app.lastCpuTime = app.curCpuTime;
14434 }
14435
14436 app.setRawAdj = app.curRawAdj;
14437 }
Dianne Hackborne02c88a2011-10-28 13:58:15 -070014438
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014439 if (app.curAdj != app.setAdj) {
14440 if (Process.setOomAdj(app.pid, app.curAdj)) {
Dianne Hackbornbbb09ac2011-11-30 11:31:29 -080014441 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
Dianne Hackborne02c88a2011-10-28 13:58:15 -070014442 TAG, "Set " + app.pid + " " + app.processName +
14443 " adj " + app.curAdj + ": " + app.adjType);
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014444 app.setAdj = app.curAdj;
Jeff Brown10e89712011-07-08 18:52:57 -070014445 } else {
Dianne Hackborn295e3c22011-08-25 13:19:08 -070014446 success = false;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014447 Slog.w(TAG, "Failed setting oom adj of " + app + " to " + app.curAdj);
Jeff Brown10e89712011-07-08 18:52:57 -070014448 }
14449 }
14450 if (app.setSchedGroup != app.curSchedGroup) {
14451 app.setSchedGroup = app.curSchedGroup;
14452 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
14453 "Setting process group of " + app.processName
14454 + " to " + app.curSchedGroup);
14455 if (app.waitingToKill != null &&
14456 app.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {
14457 Slog.i(TAG, "Killing " + app.toShortString() + ": " + app.waitingToKill);
14458 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
14459 app.processName, app.setAdj, app.waitingToKill);
14460 Process.killProcessQuiet(app.pid);
Dianne Hackborn295e3c22011-08-25 13:19:08 -070014461 success = false;
Jeff Brown10e89712011-07-08 18:52:57 -070014462 } else {
14463 if (true) {
14464 long oldId = Binder.clearCallingIdentity();
14465 try {
14466 Process.setProcessGroup(app.pid, app.curSchedGroup);
14467 } catch (Exception e) {
14468 Slog.w(TAG, "Failed setting process group of " + app.pid
14469 + " to " + app.curSchedGroup);
14470 e.printStackTrace();
14471 } finally {
14472 Binder.restoreCallingIdentity(oldId);
Dianne Hackborn9adb9c32010-08-13 14:09:56 -070014473 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014474 } else {
Jeff Brown10e89712011-07-08 18:52:57 -070014475 if (app.thread != null) {
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014476 try {
Jeff Brown10e89712011-07-08 18:52:57 -070014477 app.thread.setSchedulingGroup(app.curSchedGroup);
14478 } catch (RemoteException e) {
Dianne Hackborn06de2ea2009-05-21 12:56:43 -070014479 }
14480 }
14481 }
14482 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014483 }
Dianne Hackborn295e3c22011-08-25 13:19:08 -070014484 return success;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014485 }
14486
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070014487 private final ActivityRecord resumedAppLocked() {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070014488 ActivityRecord resumedActivity = mMainStack.mResumedActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014489 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070014490 resumedActivity = mMainStack.mPausingActivity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014491 if (resumedActivity == null || resumedActivity.app == null) {
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070014492 resumedActivity = mMainStack.topRunningActivityLocked(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014493 }
14494 }
14495 return resumedActivity;
14496 }
14497
Dianne Hackborn295e3c22011-08-25 13:19:08 -070014498 private final boolean updateOomAdjLocked(ProcessRecord app) {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070014499 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014500 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
14501 int curAdj = app.curAdj;
Dianne Hackborn7d608422011-08-07 16:24:18 -070014502 final boolean wasHidden = curAdj >= ProcessList.HIDDEN_APP_MIN_ADJ
14503 && curAdj <= ProcessList.HIDDEN_APP_MAX_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014504
14505 mAdjSeq++;
14506
Dianne Hackborne02c88a2011-10-28 13:58:15 -070014507 boolean success = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP, false);
Dianne Hackborn7d608422011-08-07 16:24:18 -070014508 final boolean nowHidden = app.curAdj >= ProcessList.HIDDEN_APP_MIN_ADJ
14509 && app.curAdj <= ProcessList.HIDDEN_APP_MAX_ADJ;
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014510 if (nowHidden != wasHidden) {
14511 // Changed to/from hidden state, so apps after it in the LRU
14512 // list may also be changed.
14513 updateOomAdjLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014514 }
Dianne Hackborn295e3c22011-08-25 13:19:08 -070014515 return success;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014516 }
14517
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014518 final void updateOomAdjLocked() {
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -070014519 final ActivityRecord TOP_ACT = resumedAppLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014520 final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
14521
14522 if (false) {
14523 RuntimeException e = new RuntimeException();
14524 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -080014525 Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014526 }
14527
14528 mAdjSeq++;
Dianne Hackborne02c88a2011-10-28 13:58:15 -070014529 mNewNumServiceProcs = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014530
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014531 // Let's determine how many processes we have running vs.
14532 // how many slots we have for background processes; we may want
14533 // to put multiple processes in a slot of there are enough of
14534 // them.
Dianne Hackborn7d608422011-08-07 16:24:18 -070014535 int numSlots = ProcessList.HIDDEN_APP_MAX_ADJ - ProcessList.HIDDEN_APP_MIN_ADJ + 1;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014536 int factor = (mLruProcesses.size()-4)/numSlots;
14537 if (factor < 1) factor = 1;
14538 int step = 0;
Dianne Hackborn8633e682010-04-22 16:03:41 -070014539 int numHidden = 0;
Dianne Hackborn5ce7d282010-02-12 19:30:02 -080014540
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014541 // First update the OOM adjustment for each of the
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014542 // application processes based on their current state.
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014543 int i = mLruProcesses.size();
Dianne Hackborn7d608422011-08-07 16:24:18 -070014544 int curHiddenAdj = ProcessList.HIDDEN_APP_MIN_ADJ;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014545 while (i > 0) {
14546 i--;
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014547 ProcessRecord app = mLruProcesses.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080014548 //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
Dianne Hackborne02c88a2011-10-28 13:58:15 -070014549 updateOomAdjLocked(app, curHiddenAdj, TOP_APP, true);
14550 if (curHiddenAdj < ProcessList.HIDDEN_APP_MAX_ADJ
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014551 && app.curAdj == curHiddenAdj) {
14552 step++;
14553 if (step >= factor) {
14554 step = 0;
14555 curHiddenAdj++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014556 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014557 }
14558 if (!app.killedBackground) {
Dianne Hackborn7d608422011-08-07 16:24:18 -070014559 if (app.curAdj >= ProcessList.HIDDEN_APP_MIN_ADJ) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014560 numHidden++;
14561 if (numHidden > mProcessLimit) {
14562 Slog.i(TAG, "No longer want " + app.processName
14563 + " (pid " + app.pid + "): hidden #" + numHidden);
14564 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
14565 app.processName, app.setAdj, "too many background");
14566 app.killedBackground = true;
14567 Process.killProcessQuiet(app.pid);
Dianne Hackborn8633e682010-04-22 16:03:41 -070014568 }
14569 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014570 }
14571 }
14572
Dianne Hackborne02c88a2011-10-28 13:58:15 -070014573 mNumServiceProcs = mNewNumServiceProcs;
14574
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014575 // Now determine the memory trimming level of background processes.
14576 // Unfortunately we need to start at the back of the list to do this
14577 // properly. We only do this if the number of background apps we
14578 // are managing to keep around is less than half the maximum we desire;
14579 // if we are keeping a good number around, we'll let them use whatever
14580 // memory they want.
Dianne Hackborn7d608422011-08-07 16:24:18 -070014581 if (numHidden <= (ProcessList.MAX_HIDDEN_APPS/2)) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014582 final int N = mLruProcesses.size();
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080014583 factor = numHidden/3;
14584 int minFactor = 2;
14585 if (mHomeProcess != null) minFactor++;
14586 if (mPreviousProcess != null) minFactor++;
14587 if (factor < minFactor) factor = minFactor;
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014588 step = 0;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014589 int curLevel = ComponentCallbacks2.TRIM_MEMORY_COMPLETE;
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014590 for (i=0; i<N; i++) {
14591 ProcessRecord app = mLruProcesses.get(i);
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -080014592 if (app.curAdj >= ProcessList.HOME_APP_ADJ
14593 && app.curAdj != ProcessList.SERVICE_B_ADJ
14594 && !app.killedBackground) {
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014595 if (app.trimMemoryLevel < curLevel && app.thread != null) {
14596 try {
14597 app.thread.scheduleTrimMemory(curLevel);
14598 } catch (RemoteException e) {
14599 }
Dianne Hackborn77eaaf02011-12-05 18:05:31 -080014600 if (false) {
14601 // For now we won't do this; our memory trimming seems
14602 // to be good enough at this point that destroying
14603 // activities causes more harm than good.
14604 if (curLevel >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE
14605 && app != mHomeProcess && app != mPreviousProcess) {
14606 // For these apps we will also finish their activities
14607 // to help them free memory.
14608 mMainStack.destroyActivitiesLocked(app, false, "trim");
14609 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014610 }
14611 }
14612 app.trimMemoryLevel = curLevel;
14613 step++;
14614 if (step >= factor) {
14615 switch (curLevel) {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014616 case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:
14617 curLevel = ComponentCallbacks2.TRIM_MEMORY_MODERATE;
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014618 break;
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014619 case ComponentCallbacks2.TRIM_MEMORY_MODERATE:
14620 curLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014621 break;
14622 }
14623 }
Dianne Hackborn7d608422011-08-07 16:24:18 -070014624 } else if (app.curAdj == ProcessList.HEAVY_WEIGHT_APP_ADJ) {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014625 if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_BACKGROUND
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014626 && app.thread != null) {
14627 try {
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014628 app.thread.scheduleTrimMemory(
14629 ComponentCallbacks2.TRIM_MEMORY_BACKGROUND);
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014630 } catch (RemoteException e) {
14631 }
14632 }
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014633 app.trimMemoryLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
Dianne Hackborn7d608422011-08-07 16:24:18 -070014634 } else if ((app.curAdj > ProcessList.VISIBLE_APP_ADJ || app.systemNoUi)
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014635 && app.pendingUiClean) {
14636 if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN
14637 && app.thread != null) {
14638 try {
14639 app.thread.scheduleTrimMemory(
14640 ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
14641 } catch (RemoteException e) {
14642 }
14643 }
14644 app.trimMemoryLevel = ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN;
14645 app.pendingUiClean = false;
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014646 } else {
14647 app.trimMemoryLevel = 0;
14648 }
14649 }
14650 } else {
14651 final int N = mLruProcesses.size();
14652 for (i=0; i<N; i++) {
14653 ProcessRecord app = mLruProcesses.get(i);
Dianne Hackborn7d608422011-08-07 16:24:18 -070014654 if ((app.curAdj > ProcessList.VISIBLE_APP_ADJ || app.systemNoUi)
Dianne Hackbornc68c9132011-07-29 01:25:18 -070014655 && app.pendingUiClean) {
14656 if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN
14657 && app.thread != null) {
14658 try {
14659 app.thread.scheduleTrimMemory(
14660 ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
14661 } catch (RemoteException e) {
14662 }
14663 }
14664 app.trimMemoryLevel = ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN;
14665 app.pendingUiClean = false;
14666 } else {
14667 app.trimMemoryLevel = 0;
14668 }
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014669 }
14670 }
14671
14672 if (mAlwaysFinishActivities) {
Dianne Hackborn28695e02011-11-02 21:59:51 -070014673 mMainStack.destroyActivitiesLocked(null, false, "always-finish");
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014674 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014675 }
14676
Dianne Hackborn50dc3bc2010-06-25 10:05:59 -070014677 final void trimApplications() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014678 synchronized (this) {
14679 int i;
14680
14681 // First remove any unused application processes whose package
14682 // has been removed.
14683 for (i=mRemovedProcesses.size()-1; i>=0; i--) {
14684 final ProcessRecord app = mRemovedProcesses.get(i);
14685 if (app.activities.size() == 0
14686 && app.curReceiver == null && app.services.size() == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080014687 Slog.i(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014688 TAG, "Exiting empty application process "
14689 + app.processName + " ("
14690 + (app.thread != null ? app.thread.asBinder() : null)
14691 + ")\n");
14692 if (app.pid > 0 && app.pid != MY_PID) {
Dianne Hackborn0c5001d2011-04-12 18:16:08 -070014693 EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
14694 app.processName, app.setAdj, "empty");
14695 Process.killProcessQuiet(app.pid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014696 } else {
14697 try {
14698 app.thread.scheduleExit();
14699 } catch (Exception e) {
14700 // Ignore exceptions.
14701 }
14702 }
Dianne Hackborn130b0d22011-07-26 22:07:48 -070014703 cleanUpApplicationRecordLocked(app, false, true, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014704 mRemovedProcesses.remove(i);
14705
14706 if (app.persistent) {
14707 if (app.persistent) {
14708 addAppLocked(app.info);
14709 }
14710 }
14711 }
14712 }
14713
Dianne Hackbornce86ba82011-07-13 19:33:41 -070014714 // Now update the oom adj for all processes.
14715 updateOomAdjLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014716 }
14717 }
14718
14719 /** This method sends the specified signal to each of the persistent apps */
14720 public void signalPersistentProcesses(int sig) throws RemoteException {
14721 if (sig != Process.SIGNAL_USR1) {
14722 throw new SecurityException("Only SIGNAL_USR1 is allowed");
14723 }
14724
14725 synchronized (this) {
14726 if (checkCallingPermission(android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES)
14727 != PackageManager.PERMISSION_GRANTED) {
14728 throw new SecurityException("Requires permission "
14729 + android.Manifest.permission.SIGNAL_PERSISTENT_PROCESSES);
14730 }
14731
Dianne Hackborndd71fc82009-12-16 19:24:32 -080014732 for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
14733 ProcessRecord r = mLruProcesses.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014734 if (r.thread != null && r.persistent) {
14735 Process.sendSignal(r.pid, sig);
14736 }
14737 }
14738 }
14739 }
14740
Dianne Hackborn62f20ec2011-08-15 17:40:28 -070014741 private void stopProfilerLocked(ProcessRecord proc, String path, int profileType) {
14742 if (proc == null || proc == mProfileProc) {
14743 proc = mProfileProc;
14744 path = mProfileFile;
14745 profileType = mProfileType;
14746 clearProfilerLocked();
14747 }
14748 if (proc == null) {
14749 return;
14750 }
14751 try {
14752 proc.thread.profilerControl(false, path, null, profileType);
14753 } catch (RemoteException e) {
14754 throw new IllegalStateException("Process disappeared");
14755 }
14756 }
14757
14758 private void clearProfilerLocked() {
14759 if (mProfileFd != null) {
14760 try {
14761 mProfileFd.close();
14762 } catch (IOException e) {
14763 }
14764 }
14765 mProfileApp = null;
14766 mProfileProc = null;
14767 mProfileFile = null;
14768 mProfileType = 0;
14769 mAutoStopProfiler = false;
14770 }
14771
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014772 public boolean profileControl(String process, boolean start,
Romain Guy7eabe552011-07-21 14:56:34 -070014773 String path, ParcelFileDescriptor fd, int profileType) throws RemoteException {
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014774
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014775 try {
14776 synchronized (this) {
14777 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
14778 // its own permission.
14779 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
14780 != PackageManager.PERMISSION_GRANTED) {
14781 throw new SecurityException("Requires permission "
14782 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014783 }
Dianne Hackborn62f20ec2011-08-15 17:40:28 -070014784
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014785 if (start && fd == null) {
14786 throw new IllegalArgumentException("null fd");
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014787 }
Dianne Hackborn62f20ec2011-08-15 17:40:28 -070014788
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014789 ProcessRecord proc = null;
Dianne Hackborn62f20ec2011-08-15 17:40:28 -070014790 if (process != null) {
14791 try {
14792 int pid = Integer.parseInt(process);
14793 synchronized (mPidsSelfLocked) {
14794 proc = mPidsSelfLocked.get(pid);
14795 }
14796 } catch (NumberFormatException e) {
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014797 }
Dianne Hackborn62f20ec2011-08-15 17:40:28 -070014798
14799 if (proc == null) {
14800 HashMap<String, SparseArray<ProcessRecord>> all
14801 = mProcessNames.getMap();
14802 SparseArray<ProcessRecord> procs = all.get(process);
14803 if (procs != null && procs.size() > 0) {
14804 proc = procs.valueAt(0);
14805 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014806 }
14807 }
Dianne Hackborn62f20ec2011-08-15 17:40:28 -070014808
14809 if (start && (proc == null || proc.thread == null)) {
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014810 throw new IllegalArgumentException("Unknown process: " + process);
14811 }
Dianne Hackborn62f20ec2011-08-15 17:40:28 -070014812
14813 if (start) {
14814 stopProfilerLocked(null, null, 0);
14815 setProfileApp(proc.info, proc.processName, path, fd, false);
14816 mProfileProc = proc;
14817 mProfileType = profileType;
14818 try {
14819 fd = fd.dup();
14820 } catch (IOException e) {
14821 fd = null;
14822 }
14823 proc.thread.profilerControl(start, path, fd, profileType);
14824 fd = null;
14825 mProfileFd = null;
14826 } else {
14827 stopProfilerLocked(proc, path, profileType);
14828 if (fd != null) {
14829 try {
14830 fd.close();
14831 } catch (IOException e) {
14832 }
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014833 }
14834 }
Dianne Hackborn62f20ec2011-08-15 17:40:28 -070014835
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014836 return true;
Dianne Hackborn9c8dd552009-06-23 19:22:52 -070014837 }
14838 } catch (RemoteException e) {
14839 throw new IllegalStateException("Process disappeared");
14840 } finally {
14841 if (fd != null) {
14842 try {
14843 fd.close();
14844 } catch (IOException e) {
14845 }
The Android Open Source Projectf5b4b982009-03-05 20:00:43 -080014846 }
14847 }
14848 }
Andy McFadden824c5102010-07-09 16:26:57 -070014849
14850 public boolean dumpHeap(String process, boolean managed,
14851 String path, ParcelFileDescriptor fd) throws RemoteException {
14852
14853 try {
14854 synchronized (this) {
14855 // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
14856 // its own permission (same as profileControl).
14857 if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
14858 != PackageManager.PERMISSION_GRANTED) {
14859 throw new SecurityException("Requires permission "
14860 + android.Manifest.permission.SET_ACTIVITY_WATCHER);
14861 }
14862
14863 if (fd == null) {
14864 throw new IllegalArgumentException("null fd");
14865 }
14866
14867 ProcessRecord proc = null;
14868 try {
14869 int pid = Integer.parseInt(process);
14870 synchronized (mPidsSelfLocked) {
14871 proc = mPidsSelfLocked.get(pid);
14872 }
14873 } catch (NumberFormatException e) {
14874 }
14875
14876 if (proc == null) {
14877 HashMap<String, SparseArray<ProcessRecord>> all
14878 = mProcessNames.getMap();
14879 SparseArray<ProcessRecord> procs = all.get(process);
14880 if (procs != null && procs.size() > 0) {
14881 proc = procs.valueAt(0);
14882 }
14883 }
14884
14885 if (proc == null || proc.thread == null) {
14886 throw new IllegalArgumentException("Unknown process: " + process);
14887 }
14888
Dianne Hackbornf02e57b2011-03-01 22:21:04 -080014889 boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
14890 if (!isDebuggable) {
Andy McFadden824c5102010-07-09 16:26:57 -070014891 if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
14892 throw new SecurityException("Process not debuggable: " + proc);
14893 }
14894 }
14895
14896 proc.thread.dumpHeap(managed, path, fd);
14897 fd = null;
14898 return true;
14899 }
14900 } catch (RemoteException e) {
14901 throw new IllegalStateException("Process disappeared");
14902 } finally {
14903 if (fd != null) {
14904 try {
14905 fd.close();
14906 } catch (IOException e) {
14907 }
14908 }
14909 }
14910 }
14911
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014912 /** In this method we try to acquire our lock to make sure that we have not deadlocked */
14913 public void monitor() {
14914 synchronized (this) { }
14915 }
Svetoslav Ganov54d068e2011-03-02 12:58:40 -080014916
14917 public void onCoreSettingsChange(Bundle settings) {
14918 for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
14919 ProcessRecord processRecord = mLruProcesses.get(i);
14920 try {
14921 if (processRecord.thread != null) {
14922 processRecord.thread.setCoreSettings(settings);
14923 }
14924 } catch (RemoteException re) {
14925 /* ignore */
14926 }
14927 }
14928 }
Amith Yamasani4b2e9342011-03-31 12:38:53 -070014929
14930 // Multi-user methods
14931
14932 public boolean switchUser(int userid) {
14933 // TODO
14934 return true;
14935 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014936}